Merge "Make sure we don't accidentally allow the night mode tile" into nyc-dev
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 4edf249..0c7ee2c 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -602,7 +602,9 @@
long currentTime = AnimationUtils.currentAnimationTimeMillis();
mStartTime = currentTime - seekTime;
mStartTimeCommitted = true; // do not allow start time to be compensated for jank
- if (!mRunning) {
+ if (!isPulsingInternal()) {
+ // If the animation loop hasn't started, the startTime will be adjusted in the first
+ // frame based on seek fraction.
mSeekFraction = fraction;
}
mOverallFraction = fraction;
@@ -980,6 +982,10 @@
mStarted = true;
mPaused = false;
mRunning = false;
+ // Resets mLastFrameTime when start() is called, so that if the animation was running,
+ // calling start() would put the animation in the
+ // started-but-not-yet-reached-the-first-frame phase.
+ mLastFrameTime = 0;
AnimationHandler animationHandler = AnimationHandler.getInstance();
animationHandler.addAnimationFrameCallback(this, (long) (mStartDelay * sDurationScale));
@@ -1095,7 +1101,7 @@
*/
@Override
public void reverse() {
- if (mRunning) {
+ if (isPulsingInternal()) {
long currentTime = AnimationUtils.currentAnimationTimeMillis();
long currentPlayTime = currentTime - mStartTime;
long timeLeft = getScaledDuration() - currentPlayTime;
@@ -1103,6 +1109,7 @@
mStartTimeCommitted = true; // do not allow start time to be compensated for jank
mReversing = !mReversing;
} else if (mStarted) {
+ mReversing = !mReversing;
end();
} else {
start(true);
@@ -1177,6 +1184,15 @@
}
/**
+ * Internal only: This tracks whether the animation has gotten on the animation loop. Note
+ * this is different than {@link #isRunning()} in that the latter tracks the time after start()
+ * is called (or after start delay if any), which may be before the animation loop starts.
+ */
+ private boolean isPulsingInternal() {
+ return mLastFrameTime > 0;
+ }
+
+ /**
* Returns the name of this animator for debugging purposes.
*/
String getNameForTrace() {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index e526c17..1e4ffbe 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1340,9 +1340,14 @@
/** @hide */
public void setUserRestriction(int code, boolean restricted, IBinder token,
String[] exceptionPackages) {
+ setUserRestrictionForUser(code, restricted, token, exceptionPackages, mContext.getUserId());
+ }
+
+ /** @hide */
+ public void setUserRestrictionForUser(int code, boolean restricted, IBinder token,
+ String[] exceptionPackages, int userId) {
try {
- mService.setUserRestriction(code, restricted, token, mContext.getUserId(),
- exceptionPackages);
+ mService.setUserRestriction(code, restricted, token, userId, exceptionPackages);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 88605db..5f6ee09 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20538,6 +20538,10 @@
if (ViewDebug.DEBUG_DRAG) {
Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
}
+ if (mAttachInfo == null) {
+ Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
+ return false;
+ }
boolean okay = false;
Point shadowSize = new Point();
@@ -20614,6 +20618,10 @@
if (ViewDebug.DEBUG_DRAG) {
Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
}
+ if (mAttachInfo == null) {
+ Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
+ return;
+ }
if (mAttachInfo.mDragToken != null) {
try {
mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
@@ -20636,6 +20644,10 @@
if (ViewDebug.DEBUG_DRAG) {
Log.d(VIEW_LOG_TAG, "updateDragShadow");
}
+ if (mAttachInfo == null) {
+ Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
+ return;
+ }
if (mAttachInfo.mDragToken != null) {
try {
Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
diff --git a/docs/html/ndk/guides/graphics/getting-started.jd b/docs/html/ndk/guides/graphics/getting-started.jd
index 145e534..0c2d939 100644
--- a/docs/html/ndk/guides/graphics/getting-started.jd
+++ b/docs/html/ndk/guides/graphics/getting-started.jd
@@ -137,7 +137,7 @@
<ol style="1">
<li>Select your project in the Android Studio <em>Project</em> panel.</li>
-<li>From the <strong>Build</strong> menu, choose <strong>Make Module <module-name> </strong>.</li>
+<li>From the <strong>Build</strong> menu, choose <strong>Make Module <module-name> </strong>; or select <strong> Build APK </strong> to generate APK.</li>
<li>Resolve any dependency issues, and then compile. As Figure 2 shows, you can select individual projects to compile by choosing them from the configuration pulldown.</li>
<img src="../images/config-pulldown.png"
diff --git a/docs/html/ndk/guides/graphics/validation-layer.jd b/docs/html/ndk/guides/graphics/validation-layer.jd
index beac1c0..1a7d832 100644
--- a/docs/html/ndk/guides/graphics/validation-layer.jd
+++ b/docs/html/ndk/guides/graphics/validation-layer.jd
@@ -6,19 +6,8 @@
<h2>On this page</h2>
<ol>
+ <li><a href="#ilp">Add Validation Layers to Project</a></li>
<li><a href="#gls">Getting Layer Source</a></li>
- <li><a href="#ias">Android Studio Integration</a>
- <ol>
- <li><a href="#asbl">Building Layers</a></li>
- <li><a href="#asil">Installing Layers</a></li>
- </ol>
- </li>
- <li><a href="#cli">Integrating on the Command Line</a>
- <ol>
- <li><a href="#clibl">Building Layers</a></li>
- <li><a href="#cliil">Installing Layers</a></li>
- </ol>
- </li>
<li><a href="#verifying">Verifying Layer Build</a></li>
<li><a href="#enabling">Enabling Layers</a></li>
<li><a href="#debug">Enabling the Debug Callback</a></li>
@@ -52,272 +41,94 @@
<p>
This page explains how to:
<ul>
+ <li>Integrate NDK's Layer Binaries.</li>
<li>Get source code for validation layers.</li>
- <li>Build the layers.</li>
- <li>Incorporate the layers into your app.</li>
+ <li>Verifying Layer Build.</li>
+ <li>Enabling Layers in Vulkan Application.</li>
+
</ul>
</p>
+<h2 id="ilp">Add Validation Layers to Project</h2>
+
+<p>
+ NDK release 12 and higher includes pre-built validation layer binaries. At
+ instance and device creation time, when requested by your application, the
+ Vulkan loader finds them in the APK installed location and loads them.
+</p>
+
+<p>
+ To use the pre-built validation layer binaries, either modify the gradle build
+ configuration of your project or manually add the binaries into the JNI
+ libraries directory of your project.
+</p>
+
+
+<h3 id="vl-gradle">Adding validation layers with Gradle</h3>
+
+<p>
+ You can add the validation layer your project using either Andorid Studio's
+ support for CMake and Ndk-build, or using Studio's experimental plugin for
+ Gradle. In general, you should use the CMake and Ndk-build configuration.
+</p>
+
+
+<p>
+ To add the libraries using Android Studio's support for CMake/Ndk-build,
+ add the following to your project's gradle configuration:
+</p>
+
+<pre class="no-pretty-print">
+sourceSets {
+ main {
+ jniLibs {
+ srcDir "${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs"
+ }
+ }
+}</pre>
+
+<p>
+ To add the libraries using Android Studio's experimental plugin for Gradle,
+ add the following to your project's gradle configuration:
+</p>
+
+<pre class="no-pretty-print">
+sources {
+ main {
+ jniLibs {
+ source.srcDir "${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs"
+ }
+ }
+}</pre>
+
+
+<h3 id="vl-jni-lib">Adding validation layers to JNI libraries</h3>
+
+<p>
+ If configuring your project's gradle build file is not working, you can
+ manually add the validation layer binaries to your project's JNI libraries
+ directory by using the following command line options:
+</p>
+
+<pre class="no-pretty-print">
+$ cd ${your-app-project-root}
+$ mkdir -p app/src/main
+$ cp -fr ${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs app/src/main/
+</pre>
+
+
<h2 id="gls">Getting Layer Source</h2>
<p>
-This section explains how to build layers from source.
-If you have precompiled layers, you can skip this section, and instead read about how to
-install your layers using <a href="#asil">Android Studio</a> or from the <a href="cliil">
-command line</a>.
-</p>
-<h3 id="ftn">From the NDK (Recommended)</h3>
-
-<p>
-<a href="{@docRoot}ndk/downloads/index.html">NDK Revision 12</a> and later contains source
-code for Android validation layers that is known-good, and ready to build. This code resides under
-the {@code <ndk-root>/sources/third_party/vulkan/src/build-android/generated/gradle-build}
-directory. This version of the layers should be sufficient for most needs. If so, your next task is
-to <a href="#building">build them</a>. Alternatively, you can pull source code from the
-Khronos Group repository.
-</pre>
-</p>
-
-<h3 id="ftr">From the repository</h3>
-
-<p>
-Although we recommend that you use the source code provided with the NDK, you can also pull more
-recent versions of the source code directly from the
+If your app needs the latest validation layer, you can pull the latest source from the Khronos Group
<a class="external-link" href="https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers">
-GitHub repository</a> belonging to the Khronos Group. To do so, perform the following steps.
+GitHub repository</a> and follow the build instructions there.
</p>
-<ol style="1">
-<li>
-Clone the Vulkan directory by entering the following command in your terminal window:
-
-<pre class="no-pretty-print">
-$ git clone git@github.com:KhronosGroup/Vulkan-LoaderAndValidationLayers.git
-</pre>
-
-<p class="note"><strong>Note: </strong>You must have a private SSH key associated with
-GitHub, or this command fails with a {@code Permission denied (publickey)} message.</p>
-</li>
-
-<li>
-Navigate to the directory containing the layer source code, and
-check out the repo's stable Android branch, called {@code android_layers}:
-
-<pre class="no-pretty-print">
-$ cd Vulkan-LoaderAndValidationLayers
-$ git checkout android_layers
-</pre>
-</li>
-
-<li>
-Begin preparation for building by entering the following commands on the command line:
-<ul>
- <li>For Linux or OS X:
- <ul>
- <li>
- <pre class="no-pretty-print">
-$ cd build-android
-$ ./android-generate</pre>
- </li>
- </ul>
- </li>
-
- <li>For Windows:
- <ul>
- <li>
-<pre class="no-pretty-print">
-> cd build-android
-> android-generate.bat</pre>
- </li>
- </ul>
- </li>
-</ul>
-</li>
-
-<li>
-Continue by following the build instructions for your platform.
-These instructions are in the {@code BUILD.md} file contained in the local instance of the
-repository you cloned.
-</li>
-</ul>
-
-</ol>
-
-<h3 id="ias">Android Studio Integration</h3>
-<p>
-Android Studio builds the validation layers when it builds the rest of the app.
-This flow makes it easier for you to trace through the layers at runtime. Each layer's
-source code corresponds to a single Gradle project, which you can specify directly in your Android
-Studio app. For example, there is a {@code build.gradle} project for threading, and another
-one for parameter validation.
-</p>
-
-<h4 id="asbl">Building layers</h4>
-
-<p>
-To integrate layers directory into Android Studio application, perform these steps:
-</p>
-<li>
-Add layers to your Android Studio application's project by specifying their corresponding
-Gradle projects in {@code settings.gradle}, which is normally a peer to app directory.
-The following example shows how to do this, based on the assumption that you're
-<a href="#ftn">using the {@code build.gradle} files from the NDK</a>.
-
-<pre>
-// configure your path to the source code generated on your machine
-def layerProjRoot = file('/path/to/ndk-root/.../build-android/generated/gradle-build')
-String[] layers = ['threading',
- 'parameter_validation',
- 'object_tracker',
- 'core_validation',
- 'device_limits',
- 'image',
- 'swapchain',
- 'unique_objects']
-for (layer in layers) {
- include ":"+ layer
- project(":" + layer.toString()).projectDir = new File("${layerProjRoot}/${layer}")
-}
-</pre>
-</li>
-
-Your next step is to provide the built layers to the app by installing them.
-
-<h4 id="asil">Installing layers</h4>
-
-<li>
-To install your layers, add the layer Gradle projects to your application's jniLibs dependencies
-in your {@code build.gradle} module. This module normally resides under the {@code app/} directory.
-The following example shows how to do this:
-
-<pre>
-android.sources {
- main {
- jni { ... }
- jniLibs {
- dependencies {
- project ":threading"
- project ":parameter_validation"
- project ":object_tracker"
- project ":core_validation"
- project ":device_limits"
- project ":image"
- project ":swapchain"
- project ":unique_objects"
- }
- }
- }
-} // android.sources
-</pre>
-</li>
-<li>
-Develop, build, and debug as you usually would. When you build, Android Studio automatically
-builds the layers and copies them into your APK.
-</li>
-<li>
-Debug your application. Android Studio allows you to trace through the layer source code.
-</li>
-<li>
-For best performance, remove the layers before you do your release build.
-</li>
-</ol>
-
-
-<h3 id="cli">From the Command Line</h3>
-
-This section explains how to build and install your layers if your project does not use
-Android Studio.
-
-<h4 id="clibl">Building layers</h4>
-
-<p>
-To build validation layers on Linux or OS X, enter these commands on the command line:
-</p>
-<ul>
-<li>
-Using Gradle:
-<pre class="no-pretty-print">
-$ cd generated/gradle-build
-$ # configure SDK and NDK path in local.properties
-$ gradlew assembleAllDebug
-</pre>
-</li>
-<li>
-Using Android makefiles:
-<pre class="no-pretty-print">
-$ ndk-build</pre>
-</li>
-</ul>
-
-<p>
-To build validation layers on Windows, enter these commands on the command line:
-</p>
-<ul>
-<li>
-Using Gradle:
-<pre class="no-pretty-print">
-> cd generated\gradle-build
-> REM configure SDK and NDK path in local.properties
-> gradlew.bat assembleAllDebug
-</pre>
-</li>
-<li>
-Using Android makefiles:
-<pre class="no-pretty-print">
-> ndk-build.cmd
-</pre>
-</li>
-</ul>
-
-
-
-</p>
-</li>
-</ol>
-
-<h4 id="cliil">Installing layers</h4>
-
-<p>
-After building the layers, you must provide them to your app. To do so, you must first
-create a {@code jniLibs} folder in your app's project directory under
-{@code ./src/main/}, and copy the libs to it. The following example shows how to do this.
-</p>
-
-<pre class="no-pretty-print">
-$ mkdir ./src/main/jniLibs
-</pre>
-
-<p>
-The next step depends on whether you are using Gradle or Android makefiles. If you're using
-Gradle, each built layer resides in its own directory. Consolidate the layers into a single
-directory, as the following example shows:
-</p>
-
-<pre class="no-pretty-print">
-$ cp -r .../build-android/generated/gradle-build/threading/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/parameter_validation/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/object_tracker/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/core_validation/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/device_limits/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/image/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/swapchain/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/unique_objects/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-</pre>
-
-If you're using Android makefiles, the built layers reside in {@code lib} folders,
-with one {@code lib} folder under each architecture’s root directory. Consolidate the
-makefiles under the {@code jniLibs} directory as this example shows:
-</p>
-<pre class="no-pretty-print">
-$ cp -r .../build-android/libs/* ./src/main/jniLibs/
-</pre>
-</li>
-</ol>
-
<h2 id="verifying">Verifying Layer Build</h2>
<p>
-Regardless of whether you build using Gradle or Android makefiles, the build process produces
-a file structure like the following:
+Regardless of whether you build with NDK's prebuilt layers or you build from the latest source code,
+the build process produces final file structure like the following:
</p>
<pre class="no-pretty-print">
@@ -571,6 +382,7 @@
</pre>
+<p>
Once your app has registered and enabled the debug callback, the system routes debugging
messages to a callback that you register. An example of such a callback appears below:
</p>
diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd
index 9bed9d5..20f219d 100644
--- a/docs/html/training/wearables/data-layer/events.jd
+++ b/docs/html/training/wearables/data-layer/events.jd
@@ -22,21 +22,21 @@
<h2 id="Wait">Wait for the Status of Data Layer Calls</h2>
<p>You'll notice that calls to the Data Layer API sometimes return a
-<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>,
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>,
such as
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>putDataItem()</code></a>.
-As soon as the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> is created,
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>putDataItem()</code></a>.
+As soon as the <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> is created,
the operation is queued in the background. If you do nothing else after this, the operation
eventually completes silently. However, you'll usually want to do something with the result
after the operation completes, so the
-<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
lets you wait for the result status, either synchronously or asynchronously.
</p>
<h3 id="async-waiting">Asynchronous calls</h3>
<p>If your code is running on the main UI thread, do not make blocking calls
to the Data Layer API. You can run the calls asynchronously by adding a callback method
-to the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> object,
+to the <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> object,
which fires when the operation is completed:</p>
<pre>
pendingResult.setResultCallback(new ResultCallback<DataItemResult>() {
@@ -51,12 +51,12 @@
<h3 id="sync-waiting">Synchronous calls</h3>
<p>If your code is running on a separate handler thread in a background service (which is the case
-in a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>),
+in a <a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>),
it's fine for the calls to block. In this case, you can call
-<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()"><code>await()</code></a>
-on the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html#await()"><code>await()</code></a>
+on the <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
object, which blocks until the request completes and returns a
-<a href="{@docRoot}reference/com/google/android/gms/common/api/Result.html"><code>Result</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/Result.html"><code>Result</code></a>
object:
</p>
@@ -79,7 +79,7 @@
</p>
<ul>
<li>Create a service that extends <a href
-="https://developer.android.com/reference/com/google/android/gms/wearable/WearableListenerService.html">
+="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html">
{@code WearableListenerService}</a>.</li>
<li>Create an activity that implements <a
href="https://developer.android.com/reference/com/google/android/gms/wearable/DataApi.DataListener.html">
@@ -215,7 +215,7 @@
<p>
An intent filter for the
-<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html">
{@code WearableListenerService}</a> example shown in the previous section might look like this:
<pre>
@@ -250,14 +250,14 @@
or path prefix, you must specify a wildcard or specific host.
If you do not do so, the system ignores the path you specified.
</p>
+
<p>
For more information on the filter types that Wear supports, see the
API reference documentation for <a
href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService">
{@code WearableListenerService}</a>.
-
-
</p>
+
<p>
For more information on data filters and matching rules, see the API reference
documentation for the <a
@@ -265,7 +265,6 @@
manifest element.
</p>
-
<p>When matching intent filters, there are two important rules to remember:</p>
<ul>
<li>If a scheme is not specified for the intent filter, the system ignores
@@ -282,10 +281,10 @@
implementing one or more of the following interfaces:
</p>
<ul>
- <li><a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>
+ <li><a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>
DataApi.DataListener</code></a></li>
- <li><a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.MessageListener.html">
+ <li><a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.MessageListener.html">
<code>MessageApi.MessageListener</code></a></li>
<li><a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi.CapabilityListener.html">{@code CapabilityApi.CapabilityListener}</a></li>
@@ -295,21 +294,21 @@
<ol>
<li>Implement the desired interfaces.</li>
<li>In {@link android.app.Activity#onCreate onCreate()}, create an instance of
-<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code>
</a>to work with the Data Layer API.</li>
<li>
-In {@link android.app.Activity#onStart onStart()}, call <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()">
+In {@link android.app.Activity#onStart onStart()}, call <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()">
<code>connect()</code></a> to connect the client to Google Play services.
</li>
<li>When the connection to Google Play services is established, the system calls
-<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>. This is where you call
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>. This is where you call
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)">
<code>DataApi.addListener()</code></a>,
-<a href="{@docRoot}android/reference/com/google/android/gms/wearable/CapabilityApi.CapabilityListener">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener, android.net.Uri, int)">
<code>MessageApi.addListener()</code></a>, or
<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.wearable.CapabilityApi.CapabilityListener,%20android.net.Uri,%20int)">
@@ -317,14 +316,16 @@
interested in listening for data layer events.</li>
<li>In {@link android.app.Activity#onStop onStop()}, unregister any listeners with
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.removeListener()</code></a>,
-<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.removeListener()</code></a>, or
-<a href="http://developer.android.com/reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.wearable.MessageApi.MessageListener)">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.removeListener()</code></a>,
+
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.removeListener()</code></a>, or
+
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.CapabilityApi.CapabilityListener)">
{@code CapabilityApi.removeListener()}</a>.</li>
<p>An alternative to adding listeners in
-<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>
and removing them in
{@link android.app.Activity#onStop onStop()} is to add a filtered listener in an activity’s {@link android.app.Activity#onResume onResume()} and
remove it in {@link android.app.Activity#onPause onPause()}, so as to only receive data that is relevant to the
@@ -332,18 +333,18 @@
<li>Implement
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.DataListener.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)">
<code>onDataChanged()</code></a>,
<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.MessageListener.html#onMessageReceived(com.google.android.gms.wearable.MessageEvent)">
<code>onMessageReceived()</code></a>,
<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html#onCapabilityChanged(com.google.android.gms.wearable.CapabilityInfo)">
{@code onCapabilityChanged()}</a>,
-or methods from <a href="http://developer.android.com/reference/com/google/android/gms/wearable/ChannelApi.ChannelListener.html">
+or methods from <a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelApi.ChannelListener.html">
Channel API listener methods</a>, depending on the interfaces that you implemented.</li>
</ol>
<p>Here's an example that implements
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>:</p>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>:</p>
<pre>
public class MainActivity extends Activity implements
@@ -403,7 +404,7 @@
<h3>Using Filters with Listener Activities</h3>
<p>
Just as you can specify intent filters for manifest-based
-<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html">
<code>WearableListenerService</code></a> objects, you can also use intent filters when registering a
listener through the Wearable API. The same rules are applicable to both
API-based listeners manifest-based listeners.
@@ -411,7 +412,7 @@
<p>
A common pattern is to register a listener with a specific path or path prefix
-in an activity’s{@link android.app.Activity#onResume onResume()} method, and to
+in an activity’s {@link android.app.Activity#onResume onResume()} method, and to
remove the listener in the activity’s {@link android.app.Activity#onPause onPause()} method.
Implementing listeners in this fashion allows your application to more selectively receive events,
improving its design and efficiency.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 8ec6a2f..777ed6a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -28,6 +28,8 @@
import android.os.Handler;
import android.os.Looper;
import android.service.quicksettings.TileService;
+import android.widget.Button;
+
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTile.DrawableIcon;
@@ -110,6 +112,8 @@
}
TileInfo info = new TileInfo();
info.state = state;
+ info.state.minimalAccessibilityClassName = info.state.expandedAccessibilityClassName =
+ Button.class.getName();
info.spec = spec;
info.appLabel = appLabel;
info.isSystem = isSystem;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 41869dd..e503c56 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -209,7 +209,9 @@
EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
} else {
// Dismiss the task if we fail to launch it
- taskView.dismissTask();
+ if (taskView != null) {
+ taskView.dismissTask();
+ }
// Keep track of failed launches
EventBus.getDefault().send(new LaunchTaskFailedEvent());
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 3d1370a..3333aa8 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -752,20 +752,12 @@
rsnScriptForEach(mContext, id, slot, ains, aout, params, limits);
}
- native void rsnScriptReduce(long con, long id, int slot, long ain,
+ native void rsnScriptReduce(long con, long id, int slot, long[] ains,
long aout, int[] limits);
- synchronized void nScriptReduce(long id, int slot, long ain, long aout,
+ synchronized void nScriptReduce(long id, int slot, long ains[], long aout,
int[] limits) {
validate();
- rsnScriptReduce(mContext, id, slot, ain, aout, limits);
- }
-
- native void rsnScriptReduceNew(long con, long id, int slot, long[] ains,
- long aout, int[] limits);
- synchronized void nScriptReduceNew(long id, int slot, long ains[], long aout,
- int[] limits) {
- validate();
- rsnScriptReduceNew(mContext, id, slot, ains, aout, limits);
+ rsnScriptReduce(mContext, id, slot, ains, aout, limits);
}
native void rsnScriptInvokeV(long con, long id, int slot, byte[] params);
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index fc3280b..13d5fcd 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -286,35 +286,6 @@
}
/**
- * Only intended for use by generated reflected code. (Simple reduction)
- *
- * @hide
- */
- protected void reduce(int slot, Allocation ain, Allocation aout, LaunchOptions sc) {
- mRS.validate();
- mRS.validateObject(ain);
- mRS.validateObject(aout);
-
- if (ain == null || aout == null) {
- throw new RSIllegalArgumentException(
- "Both ain and aout are required to be non-null.");
- }
-
- long in_id = ain.getID(mRS);
- long out_id = aout.getID(mRS);
-
- int[] limits = null;
- if (sc != null) {
- limits = new int[2];
-
- limits[0] = sc.xstart;
- limits[1] = sc.xend;
- }
-
- mRS.nScriptReduce(getID(mRS), slot, in_id, out_id, limits);
- }
-
- /**
* Only intended for use by generated reflected code. (General reduction)
*
*/
@@ -350,7 +321,7 @@
limits[5] = sc.zend;
}
- mRS.nScriptReduceNew(getID(mRS), slot, in_ids, out_id, limits);
+ mRS.nScriptReduce(getID(mRS), slot, in_ids, out_id, limits);
}
long[] mInIdsBuffer;
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index e0f5934..aa2a607 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -2094,67 +2094,10 @@
static void
nScriptReduce(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
- jlong ain, jlong aout, jintArray limits)
+ jlongArray ains, jlong aout, jintArray limits)
{
if (kLogApi) {
- ALOGD("nScriptReduce, con(%p), s(%p), slot(%i) ain(%" PRId64 ") aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ain, aout);
- }
-
- RsScriptCall sc, *sca = nullptr;
- uint32_t sc_size = 0;
-
- jint limit_len = 0;
- jint *limit_ptr = nullptr;
-
- // If the caller passed limits, reflect them in the RsScriptCall.
- if (limits != nullptr) {
- limit_len = _env->GetArrayLength(limits);
- limit_ptr = _env->GetIntArrayElements(limits, nullptr);
- if (limit_ptr == nullptr) {
- ALOGE("Failed to get Java array elements");
- return;
- }
-
- // We expect to be passed an array [x1, x2] which specifies
- // the sub-range for a 1-dimensional reduction.
- assert(limit_len == 2);
- UNUSED(limit_len); // As the assert might not be compiled.
-
- sc.xStart = limit_ptr[0];
- sc.xEnd = limit_ptr[1];
- sc.yStart = 0;
- sc.yEnd = 0;
- sc.zStart = 0;
- sc.zEnd = 0;
- sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
- sc.arrayStart = 0;
- sc.arrayEnd = 0;
- sc.array2Start = 0;
- sc.array2End = 0;
- sc.array3Start = 0;
- sc.array3End = 0;
- sc.array4Start = 0;
- sc.array4End = 0;
-
- sca = ≻
- sc_size = sizeof(sc);
- }
-
- rsScriptReduce((RsContext)con, (RsScript)script, slot,
- (RsAllocation)ain, (RsAllocation)aout,
- sca, sc_size);
-
- if (limits != nullptr) {
- _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
- }
-}
-
-static void
-nScriptReduceNew(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
- jlongArray ains, jlong aout, jintArray limits)
-{
- if (kLogApi) {
- ALOGD("nScriptReduceNew, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
+ ALOGD("nScriptReduce, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
}
if (ains == nullptr) {
@@ -2233,9 +2176,9 @@
sc_size = sizeof(sc);
}
- rsScriptReduceNew((RsContext)con, (RsScript)script, slot,
- in_allocs, in_len, (RsAllocation)aout,
- sca, sc_size);
+ rsScriptReduce((RsContext)con, (RsScript)script, slot,
+ in_allocs, in_len, (RsAllocation)aout,
+ sca, sc_size);
_env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
@@ -2951,8 +2894,7 @@
{"rsnScriptInvokeV", "(JJI[B)V", (void*)nScriptInvokeV },
{"rsnScriptForEach", "(JJI[JJ[B[I)V", (void*)nScriptForEach },
-{"rsnScriptReduce", "(JJIJJ[I)V", (void*)nScriptReduce },
-{"rsnScriptReduceNew", "(JJI[JJ[I)V", (void*)nScriptReduceNew },
+{"rsnScriptReduce", "(JJI[JJ[I)V", (void*)nScriptReduce },
{"rsnScriptSetVarI", "(JJII)V", (void*)nScriptSetVarI },
{"rsnScriptGetVarI", "(JJI)I", (void*)nScriptGetVarI },
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index cea76f2..ab5d4b6 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -621,6 +621,9 @@
for (int i = 0; i < recentsCount; i++) {
final TaskRecord tr = get(i);
if (task != tr) {
+ if (task.stack != tr.stack) {
+ continue;
+ }
if (task.userId != tr.userId) {
continue;
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 3700c71..b4c4bd8 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -46,11 +46,12 @@
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.service.vr.VrListenerService;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
-
import com.android.internal.R;
+import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.utils.ManagedApplicationService.PendingEvent;
@@ -67,6 +68,7 @@
import java.util.Collection;
import java.util.Date;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
/**
@@ -197,29 +199,44 @@
private final class NotificationAccessManager {
private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
+ private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
+ new ArrayMap<>();
public void update(Collection<String> packageNames) {
int currentUserId = ActivityManager.getCurrentUser();
- UserHandle currentUserHandle = new UserHandle(currentUserId);
-
ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
if (allowed == null) {
allowed = new ArraySet<>();
}
+ // Make sure we revoke notification access for listeners in other users
+ final int listenerCount = mNotificationAccessPackageToUserId.size();
+ for (int i = listenerCount - 1; i >= 0; i--) {
+ final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
+ if (grantUserId != currentUserId) {
+ String packageName = mNotificationAccessPackageToUserId.keyAt(i);
+ revokeNotificationListenerAccess(packageName, grantUserId);
+ revokeNotificationPolicyAccess(packageName);
+ revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
+ mNotificationAccessPackageToUserId.removeAt(i);
+ }
+ }
+
for (String pkg : allowed) {
if (!packageNames.contains(pkg)) {
- revokeNotificationListenerAccess(pkg);
+ revokeNotificationListenerAccess(pkg, currentUserId);
revokeNotificationPolicyAccess(pkg);
- revokeCoarseLocationAccess(pkg, currentUserHandle);
+ revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
+ mNotificationAccessPackageToUserId.remove(pkg);
}
}
for (String pkg : packageNames) {
if (!allowed.contains(pkg)) {
grantNotificationPolicyAccess(pkg);
- grantNotificationListenerAccess(pkg, currentUserHandle);
- grantCoarseLocationAccess(pkg, currentUserHandle);
+ grantNotificationListenerAccess(pkg, currentUserId);
+ grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
+ mNotificationAccessPackageToUserId.put(pkg, currentUserId);
}
}
@@ -229,7 +246,6 @@
}
}
-
/**
* Called when a user, package, or setting changes that could affect whether or not the
* currently bound VrListenerService is changed.
@@ -535,17 +551,33 @@
}
}
- private void updateOverlayStateLocked(ComponentName exemptedComponent) {
+ private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
+ AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+
+ // If user changed drop restrictions for the old user.
+ if (oldUserId != newUserId) {
+ appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ false, mOverlayToken, null, oldUserId);
+ }
+
+ // Apply the restrictions for the current user based on vr state
+ String[] exemptions = (exemptedPackage == null) ? new String[0] :
+ new String[] { exemptedPackage };
+
+ appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ mVrModeEnabled, mOverlayToken, exemptions, newUserId);
+ }
+
+ private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
+ String oldVrServicePackage, int oldUserId) {
+ // If VR state changed and we also have a VR service change.
+ if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
+ return;
+ }
final long identity = Binder.clearCallingIdentity();
try {
- AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
- if (appOpsManager != null) {
- String[] exemptions = (exemptedComponent == null) ? new String[0] :
- new String[] { exemptedComponent.getPackageName() };
-
- appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
- mVrModeEnabled, mOverlayToken, exemptions);
- }
+ // Set overlay exception state based on VR enabled and current service
+ updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -578,8 +610,12 @@
return validUserComponent; // Disabled -> Disabled transition does nothing.
}
+ String oldVrServicePackage = mCurrentVrService != null
+ ? mCurrentVrService.getComponent().getPackageName() : null;
+ final int oldUserId = mCurrentVrModeUser;
+
// Always send mode change events.
- changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null);
+ changeVrModeLocked(enabled);
if (!enabled || !validUserComponent) {
// Unbind whatever is running
@@ -606,12 +642,25 @@
}
}
- if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
+ if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
mCurrentVrModeComponent = calling;
+ sendUpdatedCaller = true;
+ }
+
+ if (mCurrentVrModeUser != userId) {
mCurrentVrModeUser = userId;
sendUpdatedCaller = true;
}
+ String newVrServicePackage = mCurrentVrService != null
+ ? mCurrentVrService.getComponent().getPackageName() : null;
+ final int newUserId = mCurrentVrModeUser;
+
+ // Update AppOps settings that change state when entering/exiting VR mode, or changing
+ // the current VrListenerService.
+ updateDependentAppOpsLocked(newVrServicePackage, newUserId,
+ oldVrServicePackage, oldUserId);
+
if (mCurrentVrService != null && sendUpdatedCaller) {
final ComponentName c = mCurrentVrModeComponent;
mCurrentVrService.sendEvent(new PendingEvent() {
@@ -645,18 +694,6 @@
return true;
}
- private void grantCoarseLocationAccess(String pkg, UserHandle userId) {
- PackageManager pm = mContext.getPackageManager();
- pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION,
- userId);
- }
-
- private void revokeCoarseLocationAccess(String pkg, UserHandle userId) {
- PackageManager pm = mContext.getPackageManager();
- pm.revokeRuntimePermission(pkg,
- android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
- }
-
private void grantNotificationPolicyAccess(String pkg) {
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
nm.setNotificationPolicyAccessGranted(pkg, true);
@@ -670,14 +707,14 @@
nm.setNotificationPolicyAccessGranted(pkg, false);
}
- private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
+ private void grantNotificationListenerAccess(String pkg, int userId) {
PackageManager pm = mContext.getPackageManager();
ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
- userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE,
+ userId, NotificationListenerService.SERVICE_INTERFACE,
android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
ContentResolver resolver = mContext.getContentResolver();
- ArraySet<String> current = getCurrentNotifListeners(resolver);
+ ArraySet<String> current = getNotificationListeners(resolver, userId);
for (ComponentName c : possibleServices) {
String flatName = c.flattenToString();
@@ -689,14 +726,16 @@
if (current.size() > 0) {
String flatSettings = formatSettings(current);
- Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
- flatSettings);
+ Settings.Secure.putStringForUser(resolver,
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+ flatSettings, userId);
}
}
- private void revokeNotificationListenerAccess(String pkg) {
+ private void revokeNotificationListenerAccess(String pkg, int userId) {
ContentResolver resolver = mContext.getContentResolver();
- ArraySet<String> current = getCurrentNotifListeners(resolver);
+
+ ArraySet<String> current = getNotificationListeners(resolver, userId);
ArrayList<String> toRemove = new ArrayList<>();
@@ -710,14 +749,37 @@
current.removeAll(toRemove);
String flatSettings = formatSettings(current);
- Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
- flatSettings);
-
+ Settings.Secure.putStringForUser(resolver,
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+ flatSettings, userId);
}
- private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
- String flat = Settings.Secure.getString(resolver,
- Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+ private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
+ // Don't clobber the user if permission set in current state explicitly
+ if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
+ mContext.getPackageManager().grantRuntimePermission(pkg,
+ Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+ }
+ }
+
+ private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
+ // Don't clobber the user if permission set in current state explicitly
+ if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
+ mContext.getPackageManager().revokeRuntimePermission(pkg,
+ Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+ }
+ }
+
+ private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
+ final int flags = mContext.getPackageManager().getPermissionFlags(
+ permission, pkg, new UserHandle(userId));
+ return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
+ | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
+ }
+
+ private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
+ String flat = Settings.Secure.getStringForUser(resolver,
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
ArraySet<String> current = new ArraySet<>();
if (flat != null) {
@@ -763,9 +825,8 @@
* Note: Must be called while holding {@code mLock}.
*
* @param enabled new state of the VR mode.
- * @param exemptedComponent a component to exempt from AppOps restrictions for overlays.
*/
- private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) {
+ private void changeVrModeLocked(boolean enabled) {
if (mVrModeEnabled != enabled) {
mVrModeEnabled = enabled;
@@ -773,7 +834,6 @@
Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
setVrModeNative(mVrModeEnabled);
- updateOverlayStateLocked(exemptedComponent);
onVrModeChangedLocked();
}
}