Merge "Added support for static vs. dynamic stacks"
diff --git a/api/current.txt b/api/current.txt
index 6d9c18a..090e636 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22723,7 +22723,7 @@
field public static final int KITKAT_WATCH = 20; // 0x14
field public static final int LOLLIPOP = 21; // 0x15
field public static final int LOLLIPOP_MR1 = 22; // 0x16
- field public static final int MNC = 23; // 0x17
+ field public static final int M = 23; // 0x17
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 137e56c..0513b5a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -24669,7 +24669,7 @@
field public static final int KITKAT_WATCH = 20; // 0x14
field public static final int LOLLIPOP = 21; // 0x15
field public static final int LOLLIPOP_MR1 = 22; // 0x16
- field public static final int MNC = 23; // 0x17
+ field public static final int M = 23; // 0x17
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 1de8f98..fb03b62 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -720,7 +720,7 @@
}
// Reject this timezone if it isn't an Olson zone we recognize.
- if (mTargetSdkVersion >= Build.VERSION_CODES.MNC) {
+ if (mTargetSdkVersion >= Build.VERSION_CODES.M) {
boolean hasTimeZone = false;
try {
hasTimeZone = ZoneInfoDB.getInstance().hasTimeZone(timeZone);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 862d235..42ac67c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1234,6 +1234,14 @@
}
/** @hide */
+ public void setUidMode(int code, int uid, int mode) {
+ try {
+ mService.setUidMode(code, uid, mode);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /** @hide */
public void setMode(int code, int uid, String packageName, int mode) {
try {
mService.setMode(code, uid, packageName, mode);
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 7fbb99a..4b670cd 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -240,7 +240,7 @@
getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK));
}
final boolean targetsM = decorView == null || decorView.getContext()
- .getApplicationInfo().targetSdkVersion >= VERSION_CODES.MNC;
+ .getApplicationInfo().targetSdkVersion >= VERSION_CODES.M;
ArrayList<String> sharedElementNames = targetsM ? mSharedElementNames :
mAllSharedElementNames;
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, this,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b2b1727..f21422e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -112,7 +112,7 @@
*
* In version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this intent must contain the
* extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
- * As of {@link android.os.Build.VERSION_CODES#MNC}, it should contain the extra
+ * As of {@link android.os.Build.VERSION_CODES#M}, it should contain the extra
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead, although specifying only
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported.
*
@@ -417,7 +417,7 @@
*
* <p><strong>Note:</strong> for devices running {@link android.os.Build.VERSION_CODES#LOLLIPOP}
* and {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} only SHA-1 hash is supported.
- * Starting from {@link android.os.Build.VERSION_CODES#MNC}, this parameter accepts SHA-256 in
+ * Starting from {@link android.os.Build.VERSION_CODES#M}, this parameter accepts SHA-256 in
* addition to SHA-1. Support for SHA-1 is likely to be removed in future OS releases.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
@@ -590,7 +590,7 @@
* <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li></ul>
*
* <p>
- * As of {@link android.os.Build.VERSION_CODES#MNC}, the properties should contain
+ * As of {@link android.os.Build.VERSION_CODES#M}, the properties should contain
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead of
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}, (although specifying only
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported).
@@ -603,7 +603,7 @@
* @hide
* This MIME type is used for starting the Device Owner provisioning that requires
* new provisioning features introduced in API version
- * {@link android.os.Build.VERSION_CODES#MNC} in addition to those supported in earlier
+ * {@link android.os.Build.VERSION_CODES#M} in addition to those supported in earlier
* versions.
*
* <p>During device owner provisioning a device admin app is set as the owner of the device.
@@ -2415,7 +2415,7 @@
* <p>The calling device admin must be a device or profile owner. If it is not, a
* security exception will be thrown.
*
- * <p>From version {@link android.os.Build.VERSION_CODES#MNC} disabling screen capture also
+ * <p>From version {@link android.os.Build.VERSION_CODES#M} disabling screen capture also
* blocks assist requests for all activities of the relevant user.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -2499,9 +2499,9 @@
* this method; if it has not, a security exception will be thrown.
*
* <p>Calling this from a managed profile before version
- * {@link android.os.Build.VERSION_CODES#MNC} will throw a security exception.
+ * {@link android.os.Build.VERSION_CODES#M} will throw a security exception.
*
- * <p>From version {@link android.os.Build.VERSION_CODES#MNC} a profile owner can set:
+ * <p>From version {@link android.os.Build.VERSION_CODES#M} a profile owner can set:
* <ul>
* <li>{@link #KEYGUARD_DISABLE_TRUST_AGENTS}, {@link #KEYGUARD_DISABLE_FINGERPRINT}
* these will affect the profile's parent user.
@@ -3623,7 +3623,7 @@
* @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
* user could not be created.
*
- * @deprecated From {@link android.os.Build.VERSION_CODES#MNC}
+ * @deprecated From {@link android.os.Build.VERSION_CODES#M}
*/
@Deprecated
public UserHandle createUser(@NonNull ComponentName admin, String name) {
@@ -3660,7 +3660,7 @@
* @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
* user could not be created.
*
- * @deprecated From {@link android.os.Build.VERSION_CODES#MNC}
+ * @deprecated From {@link android.os.Build.VERSION_CODES#M}
*/
@Deprecated
public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
@@ -3914,7 +3914,7 @@
* <p>Any packages that shares uid with an allowed package will also be allowed
* to activate lock task.
*
- * From {@link android.os.Build.VERSION_CODES#MNC} removing packages from the lock task
+ * From {@link android.os.Build.VERSION_CODES#M} removing packages from the lock task
* package list results in locked tasks belonging to those packages to be finished.
*
* This function can only be called by the device owner.
@@ -3982,14 +3982,14 @@
* <li>{@link Settings.Global#USB_MASS_STORAGE_ENABLED}</li>
* <li>{@link Settings.Global#WIFI_SLEEP_POLICY}</li>
* <li>{@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN}
- * This setting is only available from {@link android.os.Build.VERSION_CODES#MNC} onwards
+ * This setting is only available from {@link android.os.Build.VERSION_CODES#M} onwards
* and can only be set if {@link #setMaximumTimeToLock} is not used to set a timeout.</li>
* <li>{@link Settings.Global#WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN}</li>
- * This setting is only available from {@link android.os.Build.VERSION_CODES#MNC} onwards.
+ * This setting is only available from {@link android.os.Build.VERSION_CODES#M} onwards.
* </li>
* </ul>
* <p>Changing the following settings has no effect as of
- * {@link android.os.Build.VERSION_CODES#MNC}:
+ * {@link android.os.Build.VERSION_CODES#M}:
* <ul>
* <li>{@link Settings.Global#BLUETOOTH_ON}.
* Use {@link android.bluetooth.BluetoothAdapter#enable()} and
@@ -4344,7 +4344,7 @@
* the permission grant state via {@link #setPermissionGrantState}.
*
* <p/>As this policy only acts on runtime permission requests, it only applies to applications
- * built with a {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#MNC} or later.
+ * built with a {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later.
*
* @param admin Which profile or device owner this request is associated with.
* @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT},
@@ -4388,7 +4388,7 @@
* revoke the permission. It retains the previous grant, if any.
*
* <p/>Permissions can be granted or revoked only for applications built with a
- * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#MNC} or later.
+ * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later.
*
* @param admin Which profile or device owner this request is associated with.
* @param packageName The application to grant or revoke a permission to.
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index e08686c..6b720c0 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1106,7 +1106,7 @@
@Override
public void setAssistBlocked(boolean state) {
mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED)
- | (state ? 0 : ViewNode.FLAGS_ASSIST_BLOCKED);
+ | (state ? ViewNode.FLAGS_ASSIST_BLOCKED : 0);
}
@Override
@@ -1412,6 +1412,9 @@
if (extras != null) {
Log.i(TAG, prefix + " Extras: " + extras);
}
+ if (node.isAssistBlocked()) {
+ Log.i(TAG, prefix + " BLOCKED");
+ }
final int NCHILDREN = node.getChildCount();
if (NCHILDREN > 0) {
Log.i(TAG, prefix + " Children:");
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index 4d2158f..954ccef 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -415,7 +415,7 @@
* if this method returns TRANSPORT_OK. To avoid storing such payloads the transport
* must recognize this case and return TRANSPORT_PACKAGE_REJECTED.
*
- * Added in MNC (API 23).
+ * Added in {@link android.os.Build.VERSION_CODES#M}.
*
* @param size The estimated size of the full-data payload for this app. This includes
* manifest and archive format overhead, but is not guaranteed to be precise.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index f786d2f..aaaa745 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1021,7 +1021,7 @@
* numbers. Applications can <strong>dial</strong> emergency numbers using
* {@link #ACTION_DIAL}, however.
*
- * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#MNC MNC}
+ * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M}
* and above and declares as using the {@link android.Manifest.permission#CALL_PHONE}
* permission which is not granted, then attempting to use this action will
* result in a {@link java.lang.SecurityException}.
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index d456b5e..5d405f9 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -19,7 +19,6 @@
import android.annotation.SystemApi;
import android.os.Build;
import android.os.Handler;
-import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
@@ -1632,7 +1631,7 @@
if (values == null) {
throw new IllegalArgumentException("sensor data cannot be null");
}
- int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.MNC);
+ int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.M);
if (values.length != expectedNumValues) {
throw new IllegalArgumentException ("Wrong number of values for sensor " +
sensor.getName() + " actual=" + values.length + " expected=" +
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a82640f..10373cf 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -896,7 +896,7 @@
*
* @deprecated Deprecated in favor of the cleaner
* {@link #requestNetwork(NetworkRequest, NetworkCallback)} API.
- * In {@link VERSION_CODES#MNC}, and above, this method is unsupported and will
+ * In {@link VERSION_CODES#M}, and above, this method is unsupported and will
* throw {@code UnsupportedOperationException} if called.
*/
public int startUsingNetworkFeature(int networkType, String feature) {
@@ -946,7 +946,7 @@
* always indicates failure.
*
* @deprecated Deprecated in favor of the cleaner {@link #unregisterNetworkCallback} API.
- * In {@link VERSION_CODES#MNC}, and above, this method is unsupported and will
+ * In {@link VERSION_CODES#M}, and above, this method is unsupported and will
* throw {@code UnsupportedOperationException} if called.
*/
public int stopUsingNetworkFeature(int networkType, String feature) {
@@ -1364,7 +1364,7 @@
* @deprecated Deprecated in favor of the
* {@link #requestNetwork(NetworkRequest, NetworkCallback)},
* {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} API.
- * In {@link VERSION_CODES#MNC}, and above, this method is unsupported and will
+ * In {@link VERSION_CODES#M}, and above, this method is unsupported and will
* throw {@code UnsupportedOperationException} if called.
*/
public boolean requestRouteToHost(int networkType, int hostAddress) {
@@ -2878,7 +2878,7 @@
return;
}
- unsupportedStartingFrom(VERSION_CODES.MNC);
+ unsupportedStartingFrom(VERSION_CODES.M);
}
/**
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index b2ced7f..a0162f7 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -622,7 +622,7 @@
/**
* M comes after L.
*/
- public static final int MNC = 23;
+ public static final int M = 23;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7915a76..138be87 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -181,7 +181,7 @@
* Specifies if a user is disallowed from configuring VPN.
* The default value is <code>false</code>.
* This restriction has an effect in a managed profile only from
- * {@link android.os.Build.VERSION_CODES#MNC}
+ * {@link android.os.Build.VERSION_CODES#M}
*
* <p/>Key for user restrictions.
* <p/>Type: Boolean
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index e63fb04..9babf43 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -284,7 +284,7 @@
* If you don't set a ClipData, it will be copied there for you when calling
* {@link Context#startActivity(Intent)}.
*
- * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#MNC MNC} and above
+ * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
* and declares as using the {@link android.Manifest.permission#CAMERA} permission which
* is not granted, then atempting to use this action will result in a {@link
* java.lang.SecurityException}.
@@ -338,7 +338,7 @@
* If you don't set a ClipData, it will be copied there for you when calling
* {@link Context#startActivity(Intent)}.
*
- * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#MNC MNC} and above
+ * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
* and declares as using the {@link android.Manifest.permission#CAMERA} permission which
* is not granted, then atempting to use this action will result in a {@link
* java.lang.SecurityException}.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 04f1e04..862207c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4434,7 +4434,7 @@
*
* @deprecated Use {@link android.app.KeyguardManager} to determine the state and security
* level of the keyguard. Accessing this setting from an app that is targeting
- * {@link VERSION_CODES#MNC} or later throws a {@code SecurityException}.
+ * {@link VERSION_CODES#M} or later throws a {@code SecurityException}.
*/
@Deprecated
public static final String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
@@ -4443,7 +4443,7 @@
* Whether lock pattern is visible as user enters (0 = false, 1 = true)
*
* @deprecated Accessing this setting from an app that is targeting
- * {@link VERSION_CODES#MNC} or later throws a {@code SecurityException}.
+ * {@link VERSION_CODES#M} or later throws a {@code SecurityException}.
*/
@Deprecated
public static final String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
@@ -4456,7 +4456,7 @@
* lockscreen uses
* {@link Settings.System#HAPTIC_FEEDBACK_ENABLED}.
* Accessing this setting from an app that is targeting
- * {@link VERSION_CODES#MNC} or later throws a {@code SecurityException}.
+ * {@link VERSION_CODES#M} or later throws a {@code SecurityException}.
*/
@Deprecated
public static final String
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6de9cc7..17a9741 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -56,7 +56,6 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManagerGlobal;
-import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
@@ -3809,14 +3808,14 @@
// of whether a layout was requested on that View.
sIgnoreMeasureCache = targetSdkVersion < KITKAT;
- Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
+ Canvas.sCompatibilityRestore = targetSdkVersion < M;
- // In MNC and newer, our widgets can pass a "hint" value in the size
+ // In M and newer, our widgets can pass a "hint" value in the size
// for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
// know what the expected parent size is going to be, so e.g. list items can size
// themselves at 1/3 the size of their container. It breaks older apps though,
// specifically apps that use some popular open source libraries.
- sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < MNC;
+ sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
sCompatibilityDone = true;
}
@@ -4284,27 +4283,27 @@
PROVIDER_BACKGROUND));
break;
case R.styleable.View_foreground:
- if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+ if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
setForeground(a.getDrawable(attr));
}
break;
case R.styleable.View_foregroundGravity:
- if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+ if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
}
break;
case R.styleable.View_foregroundTintMode:
- if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+ if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
}
break;
case R.styleable.View_foregroundTint:
- if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+ if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
setForegroundTintList(a.getColorStateList(attr));
}
break;
case R.styleable.View_foregroundInsidePadding:
- if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+ if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
if (mForegroundInfo == null) {
mForegroundInfo = new ForegroundInfo();
}
@@ -11424,10 +11423,10 @@
* strongly recommended for performance reasons to either override
* {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
* {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
- * of the animation. On versions {@link android.os.Build.VERSION_CODES#MNC} and below,
+ * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
* the default path for rendering an unlayered View with alpha could add multiple milliseconds
* of rendering cost, even for simple or small views. Starting with
- * {@link android.os.Build.VERSION_CODES#MNC}, {@link #LAYER_TYPE_HARDWARE} is automatically
+ * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
* applied to the view at the rendering level.</p>
*
* <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
@@ -11438,7 +11437,7 @@
* associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
* alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
*
- * <p>Starting with {@link android.os.Build.VERSION_CODES#MNC}, setting a translucent alpha
+ * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
* value will clip a View to its bounds, unless the View returns <code>false</code> from
* {@link #hasOverlappingRendering}.</p>
*
@@ -18780,22 +18779,17 @@
long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
- final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
- final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
- MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
- final boolean matchingSize = isExactly &&
- getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
- getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
- if (forceLayout || !matchingSize &&
- (widthMeasureSpec != mOldWidthMeasureSpec ||
- heightMeasureSpec != mOldHeightMeasureSpec)) {
+ if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
+ widthMeasureSpec != mOldWidthMeasureSpec ||
+ heightMeasureSpec != mOldHeightMeasureSpec) {
// first clears the measured dimension flag
mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
resolveRtlPropertiesIfNeeded();
- int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
+ int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
+ mMeasureCache.indexOfKey(key);
if (cacheIndex < 0 || sIgnoreMeasureCache) {
// measure ourselves, this should set the measured dimension flag back
onMeasure(widthMeasureSpec, heightMeasureSpec);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a6639d5..bc19b40 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5488,7 +5488,7 @@
* @see #setAnimationCacheEnabled(boolean)
* @see View#setDrawingCacheEnabled(boolean)
*
- * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#M}, this property is ignored.
* Caching behavior of children may be controlled through {@link View#setLayerType(int, Paint)}.
*/
public boolean isAnimationCacheEnabled() {
@@ -5506,7 +5506,7 @@
* @see #isAnimationCacheEnabled()
* @see View#setDrawingCacheEnabled(boolean)
*
- * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#M}, this property is ignored.
* Caching behavior of children may be controlled through {@link View#setLayerType(int, Paint)}.
*/
public void setAnimationCacheEnabled(boolean enabled) {
@@ -5523,7 +5523,7 @@
* @see #setChildrenDrawnWithCacheEnabled(boolean)
* @see View#setDrawingCacheEnabled(boolean)
*
- * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#M}, this property is ignored.
* Child views may no longer have their caching behavior disabled by parents.
*/
public boolean isAlwaysDrawnWithCacheEnabled() {
@@ -5547,7 +5547,7 @@
* @see View#setDrawingCacheEnabled(boolean)
* @see View#setDrawingCacheQuality(int)
*
- * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#M}, this property is ignored.
* Child views may no longer have their caching behavior disabled by parents.
*/
public void setAlwaysDrawnWithCacheEnabled(boolean always) {
@@ -5563,7 +5563,7 @@
* @see #setAlwaysDrawnWithCacheEnabled(boolean)
* @see #setChildrenDrawnWithCacheEnabled(boolean)
*
- * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#M}, this property is ignored.
* Child views may no longer be forced to cache their rendering state by their parents.
* Use {@link View#setLayerType(int, Paint)} on individual Views instead.
*/
@@ -5584,7 +5584,7 @@
* @see #setAlwaysDrawnWithCacheEnabled(boolean)
* @see #isChildrenDrawnWithCacheEnabled()
*
- * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#M}, this property is ignored.
* Child views may no longer be forced to cache their rendering state by their parents.
* Use {@link View#setLayerType(int, Paint)} on individual Views instead.
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fdfc48a5..fb02e7e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -79,7 +79,6 @@
import com.android.internal.R;
import com.android.internal.os.SomeArgs;
import com.android.internal.policy.PhoneFallbackEventHandler;
-import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.view.BaseSurfaceHolder;
import com.android.internal.view.RootViewSurfaceTaker;
@@ -5821,7 +5820,7 @@
}
private void adjustInputEventForCompatibility(InputEvent e) {
- if (mTargetSdkVersion < Build.VERSION_CODES.MNC && e instanceof MotionEvent) {
+ if (mTargetSdkVersion < Build.VERSION_CODES.M && e instanceof MotionEvent) {
MotionEvent motion = (MotionEvent) e;
final int mask =
MotionEvent.BUTTON_STYLUS_PRIMARY | MotionEvent.BUTTON_STYLUS_SECONDARY;
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 76c8fbd..6130fd5 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -303,10 +303,12 @@
* {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and prior, do not trust this package
* name. The system had not verified the consistency between the package name here and
* application's uid. Consider to use {@link InputBinding#getUid()}, which is trustworthy.
- * Starting from Android MNC, the system verifies the consistency between this package name
- * and application uid before {@link EditorInfo} is passed to the input method.</p>
+ * Starting from {@link android.os.Build.VERSION_CODES#M}, the system verifies the consistency
+ * between this package name and application uid before {@link EditorInfo} is passed to the
+ * input method.</p>
*
- * <p><strong>Editor authors:</strong> Starting from Android MNC, the application is no longer
+ * <p><strong>Editor authors:</strong> Starting from {@link android.os.Build.VERSION_CODES#M},
+ * the application is no longer
* able to establish input connections if the package name provided here is inconsistent with
* application's uid.</p>
*/
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 47e894a..b5e08ca 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -686,7 +686,6 @@
int weightedMaxWidth = 0;
boolean allFillParent = true;
float totalWeight = 0;
- int usedExcessSpace = 0;
final int count = getVirtualChildCount();
@@ -722,10 +721,8 @@
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
totalWeight += lp.weight;
-
- final boolean fillExcessSpace = lp.weight > 0;
- final boolean hasZeroHeight = lp.height == 0;
- if (heightMode == MeasureSpec.EXACTLY && fillExcessSpace && hasZeroHeight) {
+
+ if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) {
// Optimization: don't bother measuring children who are going to use
// leftover space. These views will get measured again down below if
// there is any leftover space.
@@ -733,12 +730,14 @@
mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);
skippedMeasure = true;
} else {
- if (fillExcessSpace && hasZeroHeight) {
- // The LinearLayout's heightMode is either UNSPECIFIED or
- // AT_MOST, and this child wanted to stretch to fill
- // available space. Translate the explicit height of 0 to
- // WRAP_CONTENT so that we can measure the view's ideal
- // height.
+ int oldHeight = Integer.MIN_VALUE;
+
+ if (lp.height == 0 && lp.weight > 0) {
+ // heightMode is either UNSPECIFIED or AT_MOST, and this
+ // child wanted to stretch to fill available space.
+ // Translate that to WRAP_CONTENT so that it does not end up
+ // with a height of 0
+ oldHeight = 0;
lp.height = LayoutParams.WRAP_CONTENT;
}
@@ -750,16 +749,11 @@
child, i, widthMeasureSpec, 0, heightMeasureSpec,
totalWeight == 0 ? mTotalLength : 0);
- final int childHeight = child.getMeasuredHeight();
- if (fillExcessSpace) {
- usedExcessSpace += childHeight;
-
- // Restore original layout height.
- if (hasZeroHeight) {
- lp.height = 0;
- }
+ if (oldHeight != Integer.MIN_VALUE) {
+ lp.height = oldHeight;
}
+ final int childHeight = child.getMeasuredHeight();
final int totalLength = mTotalLength;
mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +
lp.bottomMargin + getNextLocationOffset(child));
@@ -863,7 +857,7 @@
// Either expand children with weight to take up available space or
// shrink them if they extend beyond our current bounds. If we skipped
// measurement on any children, we need to measure them now.
- final int delta = heightSize - mTotalLength + usedExcessSpace;
+ int delta = heightSize - mTotalLength;
if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
@@ -880,14 +874,34 @@
float childExtra = lp.weight;
if (childExtra > 0) {
- // Distribute excess space to child.
- final int childHeight = Math.max(0, (int) (childExtra * delta / weightSum));
- final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight,
- MeasureSpec.EXACTLY);
+ // Child said it could absorb extra space -- give him his share
+ int share = (int) (childExtra * delta / weightSum);
+ weightSum -= childExtra;
+ delta -= share;
+
final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
- mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,
- lp.width);
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ mPaddingLeft + mPaddingRight +
+ lp.leftMargin + lp.rightMargin, lp.width);
+
+ // TODO: Use a field like lp.isMeasured to figure out if this
+ // child has been previously measured
+ if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) {
+ // child was measured once already above...
+ // base new measurement on stored values
+ int childHeight = child.getMeasuredHeight() + share;
+ if (childHeight < 0) {
+ childHeight = 0;
+ }
+
+ child.measure(childWidthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
+ } else {
+ // child was skipped in the loop above.
+ // Measure for this first time here
+ child.measure(childWidthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(share > 0 ? share : 0,
+ MeasureSpec.EXACTLY));
+ }
// Child may now not fit in vertical dimension.
childState = combineMeasuredStates(childState, child.getMeasuredState()
@@ -1003,7 +1017,6 @@
int weightedMaxHeight = 0;
boolean allFillParent = true;
float totalWeight = 0;
- int usedExcessSpace = 0;
final int count = getVirtualChildCount();
@@ -1053,10 +1066,8 @@
child.getLayoutParams();
totalWeight += lp.weight;
-
- final boolean fillExcessSpace = lp.weight > 0;
- final boolean hasZeroWidth = lp.width == 0;
- if (widthMode == MeasureSpec.EXACTLY && fillExcessSpace && hasZeroWidth) {
+
+ if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) {
// Optimization: don't bother measuring children who are going to use
// leftover space. These views will get measured again down below if
// there is any leftover space.
@@ -1083,12 +1094,14 @@
skippedMeasure = true;
}
} else {
- if (fillExcessSpace && hasZeroWidth) {
- // The LinearLayout's widthMode is either UNSPECIFIED or
- // AT_MOST, and this child wanted to stretch to fill
- // available space. Translate the explicit height of 0 to
- // WRAP_CONTENT so that we can measure the view's ideal
- // width.
+ int oldWidth = Integer.MIN_VALUE;
+
+ if (lp.width == 0 && lp.weight > 0) {
+ // widthMode is either UNSPECIFIED or AT_MOST, and this
+ // child
+ // wanted to stretch to fill available space. Translate that to
+ // WRAP_CONTENT so that it does not end up with a width of 0
+ oldWidth = 0;
lp.width = LayoutParams.WRAP_CONTENT;
}
@@ -1100,16 +1113,11 @@
totalWeight == 0 ? mTotalLength : 0,
heightMeasureSpec, 0);
- final int childWidth = child.getMeasuredWidth();
- if (fillExcessSpace) {
- usedExcessSpace += childWidth;
-
- // Restore the original layout width.
- if (hasZeroWidth) {
- lp.width = 0;
- }
+ if (oldWidth != Integer.MIN_VALUE) {
+ lp.width = oldWidth;
}
+ final int childWidth = child.getMeasuredWidth();
if (isExactly) {
mTotalLength += childWidth + lp.leftMargin + lp.rightMargin +
getNextLocationOffset(child);
@@ -1234,7 +1242,7 @@
// Either expand children with weight to take up available space or
// shrink them if they extend beyond our current bounds. If we skipped
// measurement on any children, we need to measure them now.
- final int delta = widthSize - mTotalLength + usedExcessSpace;
+ int delta = widthSize - mTotalLength;
if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
@@ -1257,13 +1265,34 @@
float childExtra = lp.weight;
if (childExtra > 0) {
// Child said it could absorb extra space -- give him his share
- final int childWidth = Math.max(0, (int) (childExtra * delta / weightSum));
- final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth,
- MeasureSpec.EXACTLY);
- final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+ int share = (int) (childExtra * delta / weightSum);
+ weightSum -= childExtra;
+ delta -= share;
+
+ final int childHeightMeasureSpec = getChildMeasureSpec(
+ heightMeasureSpec,
mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin,
lp.height);
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+
+ // TODO: Use a field like lp.isMeasured to figure out if this
+ // child has been previously measured
+ if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) {
+ // child was measured once already above ... base new measurement
+ // on stored values
+ int childWidth = child.getMeasuredWidth() + share;
+ if (childWidth < 0) {
+ childWidth = 0;
+ }
+
+ child.measure(
+ MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
+ childHeightMeasureSpec);
+ } else {
+ // child was skipped in the loop above. Measure for this first time here
+ child.measure(MeasureSpec.makeMeasureSpec(
+ share > 0 ? share : 0, MeasureSpec.EXACTLY),
+ childHeightMeasureSpec);
+ }
// Child may now not fit in horizontal dimension.
childState = combineMeasuredStates(childState,
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 58a94b9..529d295 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -356,7 +356,7 @@
final int heightPadding;
final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
- if (targetSdkVersion >= VERSION_CODES.MNC) {
+ if (targetSdkVersion >= VERSION_CODES.M) {
widthPadding = mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin;
heightPadding = mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin;
} else {
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 73c4833..9fa2c23 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -38,6 +38,7 @@
int checkPackage(int uid, String packageName);
List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
+ void setUidMode(int code, int uid, int mode);
void setMode(int code, int uid, String packageName, int mode);
void resetAllModes(int reqUserId, String reqPackageName);
int checkAudioOperation(int code, int usage, int uid, String packageName);
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 43f7ebc..2b39528 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -32,7 +32,6 @@
import android.view.ActionMode;
import android.view.ContextThemeWrapper;
-import android.view.Display;
import android.view.Gravity;
import android.view.IRotationWatcher.Stub;
import android.view.IWindowManager;
@@ -3517,7 +3516,7 @@
public void onDestroyActionMode(ActionMode mode) {
mWrapped.onDestroyActionMode(mode);
final boolean isMncApp = mContext.getApplicationInfo().targetSdkVersion
- >= Build.VERSION_CODES.MNC;
+ >= Build.VERSION_CODES.M;
final boolean isPrimary;
final boolean isFloating;
if (isMncApp) {
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 1515703..de16f20 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -219,7 +219,7 @@
<flag name="appop" value="0x40" />
<!-- Additional flag from base permission type: this permission can be automatically
granted to apps that target API levels below
- {@link android.os.Build.VERSION_CODES#MNC} (before runtime permissions
+ {@link android.os.Build.VERSION_CODES#M} (before runtime permissions
were introduced). -->
<flag name="pre23" value="0x80" />
<!-- Additional flag from base permission type: this permission can be automatically
@@ -1059,7 +1059,7 @@
at the same time.
<p>The default value is <code>false</code> for applications with
- <code>targetSdkVersion</code> lesser than {@link android.os.Build.VERSION_CODES#MNC} and
+ <code>targetSdkVersion</code> lesser than {@link android.os.Build.VERSION_CODES#M} and
<code>true</code> otherwise.
<p>NOTE: A task's root activity value is applied to all additional activities launched in
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3c838b2a..cabb56c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2604,7 +2604,7 @@
<public type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
<!-- ===============================================================
- Resources added in version MNC of the platform
+ Resources added in version M of the platform
=============================================================== -->
<eat-comment />
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index c29ec0d..bde3d19 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -54,7 +54,7 @@
* can be played on a device operating at a sample rate of 48000Hz; the sample rate conversion is
* automatically handled by the platform, it will not play at 6x speed.
*
- * <p>As of API {@link android.os.Build.VERSION_CODES#MNC},
+ * <p>As of API {@link android.os.Build.VERSION_CODES#M},
* sample rates up to 192kHz are supported
* for <code>AudioRecord</code> and <code>AudioTrack</code>, with sample rate conversion
* performed as needed.
@@ -99,7 +99,7 @@
* Floats are efficiently manipulated by modern CPUs,
* have greater precision than 24 bit signed integers,
* and have greater dynamic range than 32 bit signed integers.
- * <code>AudioRecord</code> as of API {@link android.os.Build.VERSION_CODES#MNC} and
+ * <code>AudioRecord</code> as of API {@link android.os.Build.VERSION_CODES#M} and
* <code>AudioTrack</code> as of API {@link android.os.Build.VERSION_CODES#LOLLIPOP}
* support <code>ENCODING_PCM_FLOAT</code>.
* </li>
@@ -123,7 +123,7 @@
* the samples and their arrangement in the audio frame. They are also used in the endpoint (e.g.
* a USB audio interface, a DAC connected to headphones) to specify allowable configurations of a
* particular device.
- * <br>As of API {@link android.os.Build.VERSION_CODES#MNC}, there are two types of channel masks:
+ * <br>As of API {@link android.os.Build.VERSION_CODES#M}, there are two types of channel masks:
* channel position masks and channel index masks.
*
* <h5 id="channelPositionMask">Channel position masks</h5>
@@ -152,7 +152,7 @@
* {@link #CHANNEL_OUT_FRONT_RIGHT}.
*
* <h5 id="channelIndexMask">Channel index masks</h5>
- * Channel index masks are introduced in API {@link android.os.Build.VERSION_CODES#MNC}. They allow
+ * Channel index masks are introduced in API {@link android.os.Build.VERSION_CODES#M}. They allow
* the selection of a particular channel from the source or sink endpoint by number, i.e. the first
* channel, the second channel, and so forth. This avoids problems with artificially assigning
* positions to channels of an endpoint, or figuring what the i<sup>th</sup> position bit is within
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 62810c6..8880dad 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -27,7 +27,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.content.Context;
@@ -1174,9 +1173,12 @@
* Poll for a timestamp on demand.
* <p>
* If you need to track timestamps during initial warmup or after a routing or mode change,
- * you should request a new timestamp once per second until the reported timestamps
- * show that the audio clock is stable.
- * Thereafter, query for a new timestamp approximately once every 10 seconds to once per minute.
+ * you should request a new timestamp periodically until the reported timestamps
+ * show that the frame position is advancing, or until it becomes clear that
+ * timestamps are unavailable for this route.
+ * <p>
+ * After the clock is advancing at a stable rate,
+ * query for a new timestamp approximately once every 10 seconds to once per minute.
* Calling this method more often is inefficient.
* It is also counter-productive to call this method more often than recommended,
* because the short-term differences between successive timestamp reports are not meaningful.
@@ -1199,6 +1201,11 @@
* In the case that no timestamp is available, any supplied instance is left unaltered.
* A timestamp may be temporarily unavailable while the audio clock is stabilizing,
* or during and immediately after a route change.
+ * A timestamp is permanently unavailable for a given route if the route does not support
+ * timestamps. In this case, the approximate frame position can be obtained
+ * using {@link #getPlaybackHeadPosition}.
+ * However, it may be useful to continue to query for
+ * timestamps occasionally, to recover after a route change.
*/
// Add this text when the "on new timestamp" API is added:
// Use if you need to get the most recent timestamp outside of the event callback handler.
@@ -1409,7 +1416,7 @@
* <br>
* If looping is currently enabled and the new position is greater than or equal to the
* loop end marker, the behavior varies by API level:
- * as of {@link android.os.Build.VERSION_CODES#MNC},
+ * as of {@link android.os.Build.VERSION_CODES#M},
* the looping is first disabled and then the position is set.
* For earlier API levels, the behavior is unspecified.
* @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
@@ -1446,7 +1453,7 @@
* {@link #ERROR_BAD_VALUE} is returned.
* The loop range is the interval [startInFrames, endInFrames).
* <br>
- * As of {@link android.os.Build.VERSION_CODES#MNC}, the position is left unchanged,
+ * As of {@link android.os.Build.VERSION_CODES#M}, the position is left unchanged,
* unless it is greater than or equal to the loop end marker, in which case
* it is forced to the loop start marker.
* For earlier API levels, the effect on position is unspecified.
@@ -2077,7 +2084,7 @@
* The track must be stopped or paused, and
* the track's creation mode must be {@link #MODE_STATIC}.
* <p>
- * As of {@link android.os.Build.VERSION_CODES#MNC}, also resets the value returned by
+ * As of {@link android.os.Build.VERSION_CODES#M}, also resets the value returned by
* {@link #getPlaybackHeadPosition()} to zero.
* For earlier API levels, the reset behavior is unspecified.
* <p>
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 5f60891..3c459d8 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -21,12 +21,7 @@
import android.annotation.Nullable;
import android.graphics.ImageFormat;
import android.graphics.Rect;
-import android.media.Image;
-import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecList;
-import android.media.MediaCrypto;
-import android.media.MediaFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -510,11 +505,11 @@
#releaseOutputBuffer(int, long) releaseOutputBuffer(bufferId, timestamp)}.</li>
</ul>
<p>
- Since {@link android.os.Build.VERSION_CODES#MNC}, the default timestamp is the {@linkplain
+ Since {@link android.os.Build.VERSION_CODES#M}, the default timestamp is the {@linkplain
BufferInfo#presentationTimeUs presentation timestamp} of the buffer (converted to nanoseconds).
It was not defined prior to that.
<p>
- Also since {@link android.os.Build.VERSION_CODES#MNC}, you can change the output Surface
+ Also since {@link android.os.Build.VERSION_CODES#M}, you can change the output Surface
dynamically using {@link #setOutputSurface setOutputSurface}.
<h4>Using an Input Surface</h4>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 3670683..5183c35 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -142,6 +142,8 @@
private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328;
private static final int MSG_AIRPLANE_MODE_CHANGED = 329;
private static final int MSG_SERVICE_STATE_CHANGE = 330;
+ private static final int MSG_SCREEN_TURNED_ON = 331;
+ private static final int MSG_SCREEN_TURNED_OFF = 332;
private static KeyguardUpdateMonitor sInstance;
@@ -248,6 +250,12 @@
case MSG_SERVICE_STATE_CHANGE:
handleServiceStateChange(msg.arg1, (ServiceState) msg.obj);
break;
+ case MSG_SCREEN_TURNED_ON:
+ handleScreenTurnedOn();
+ break;
+ case MSG_SCREEN_TURNED_OFF:
+ handleScreenTurnedOff();
+ break;
}
}
};
@@ -806,6 +814,26 @@
updateFingerprintListeningState();
}
+ private void handleScreenTurnedOn() {
+ final int count = mCallbacks.size();
+ for (int i = 0; i < count; i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onScreenTurnedOn();
+ }
+ }
+ }
+
+ private void handleScreenTurnedOff() {
+ final int count = mCallbacks.size();
+ for (int i = 0; i < count; i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onScreenTurnedOff();
+ }
+ }
+ }
+
/**
* IMPORTANT: Must be called from UI thread.
*/
@@ -1486,12 +1514,14 @@
synchronized (this) {
mScreenOn = true;
}
+ mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
}
public void dispatchScreenTurnedOff() {
synchronized(this) {
mScreenOn = false;
}
+ mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF);
}
public boolean isDeviceInteractive() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 0cdf999..6cda2b7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -161,6 +161,16 @@
public void onFinishedGoingToSleep(int why) { }
/**
+ * Called when the screen has been turned on.
+ */
+ public void onScreenTurnedOn() { }
+
+ /**
+ * Called when the screen has been turned off.
+ */
+ public void onScreenTurnedOff() { }
+
+ /**
* Called when trust changes for a user.
*/
public void onTrustChanged(int userId) { }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index 49e6740..bafccae 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -46,6 +46,7 @@
import android.util.Slog;
import android.util.Xml;
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.HandlerCaller;
import com.android.internal.util.FastXmlSerializer;
import com.android.printspooler.R;
@@ -493,6 +494,7 @@
Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
}
+ MetricsLogger.histogram(this, "print_job_state", state);
switch (state) {
case PrintJobInfo.STATE_COMPLETED:
case PrintJobInfo.STATE_CANCELED:
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 6baa4b3..e8a5e43 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -72,6 +72,7 @@
import android.widget.Spinner;
import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
import com.android.printspooler.R;
import com.android.printspooler.model.MutexFileProvider;
import com.android.printspooler.model.PrintSpoolerProvider;
@@ -325,6 +326,7 @@
if (mState != STATE_INITIALIZING && mCurrentPrinter != null) {
mPrinterRegistry.setTrackedPrinter(mCurrentPrinter.getId());
}
+ MetricsLogger.count(this, "print_preview", 1);
}
@Override
@@ -1074,6 +1076,8 @@
private void confirmPrint() {
setState(STATE_PRINT_CONFIRMED);
+ MetricsLogger.count(this, "print_confirmed", 1);
+
updateOptionsUi();
addCurrentPrinterToHistory();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 6e3a29d..14fba2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -48,6 +48,8 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -86,6 +88,15 @@
final static String TAG = "SystemServicesProxy";
final static BitmapFactory.Options sBitmapOptions;
+ final static HandlerThread sBgThread;
+
+ static {
+ sBgThread = new HandlerThread("Recents-SystemServicesProxy",
+ android.os.Process.THREAD_PRIORITY_BACKGROUND);
+ sBgThread.start();
+ sBitmapOptions = new BitmapFactory.Options();
+ sBitmapOptions.inMutable = true;
+ }
AccessibilityManager mAccm;
ActivityManager mAm;
@@ -99,17 +110,14 @@
String mRecentsPackage;
ComponentName mAssistComponent;
+ Handler mBgThreadHandler;
+
Bitmap mDummyIcon;
int mDummyThumbnailWidth;
int mDummyThumbnailHeight;
Paint mBgProtectionPaint;
Canvas mBgProtectionCanvas;
- static {
- sBitmapOptions = new BitmapFactory.Options();
- sBitmapOptions.inMutable = true;
- }
-
/** Private constructor */
public SystemServicesProxy(Context context) {
mAccm = AccessibilityManager.getInstance(context);
@@ -122,6 +130,7 @@
mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplay = mWm.getDefaultDisplay();
mRecentsPackage = context.getPackageName();
+ mBgThreadHandler = new Handler(sBgThread.getLooper());
// Get the dummy thumbnail width/heights
Resources res = context.getResources();
@@ -373,12 +382,17 @@
}
/** Removes the task */
- public void removeTask(int taskId) {
+ public void removeTask(final int taskId) {
if (mAm == null) return;
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
// Remove the task.
- mAm.removeTask(taskId);
+ mBgThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAm.removeTask(taskId);
+ }
+ });
}
/**
@@ -646,22 +660,6 @@
return windowRect;
}
- /**
- * Takes a screenshot of the current surface.
- */
- public Bitmap takeScreenshot() {
- DisplayInfo di = new DisplayInfo();
- mDisplay.getDisplayInfo(di);
- return SurfaceControl.screenshot(di.getNaturalWidth(), di.getNaturalHeight());
- }
-
- /**
- * Takes a screenshot of the current app.
- */
- public Bitmap takeAppScreenshot() {
- return takeScreenshot();
- }
-
/** Starts an activity from recents. */
public boolean startActivityFromRecents(Context context, int taskId, String taskName,
ActivityOptions options) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index b2aa2b6..ad25c85 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -343,11 +343,14 @@
if (infoHandle.info != null) {
label = ssp.getActivityLabel(infoHandle.info);
mActivityLabelCache.put(taskKey, label);
+ return label;
} else {
Log.w(TAG, "Missing ActivityInfo for " + taskKey.baseIntent.getComponent()
+ " u=" + taskKey.userId);
}
- return label;
+ // If the activity info does not exist or fails to load, return an empty label for now,
+ // but do not cache it
+ return "";
}
/** Returns the content description using as many cached values as we can. */
@@ -358,14 +361,22 @@
if (label != null) {
return label;
}
+ // If the given activity label is empty, don't compute or cache the content description
+ if (activityLabel.isEmpty()) {
+ return "";
+ }
+
label = ssp.getContentDescription(taskKey.baseIntent, taskKey.userId, activityLabel, res);
if (label != null) {
mContentDescriptionCache.put(taskKey, label);
+ return label;
} else {
Log.w(TAG, "Missing content description for " + taskKey.baseIntent.getComponent()
+ " u=" + taskKey.userId);
}
- return label;
+ // If the content description does not exist, return an empty label for now, but do not
+ // cache it
+ return "";
}
/** Returns the activity icon using as many cached values as we can. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 78b3512..2e0b80a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -316,7 +316,7 @@
overscrollRange);
// Invalidate to kick off computeScroll
mSv.invalidate();
- } else if (mScroller.isScrollOutOfBounds()) {
+ } else if (mIsScrolling && mScroller.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
mScroller.animateBoundScroll();
} else if (mActiveTaskView == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index ccec759..71baf57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -374,7 +374,11 @@
}
private void updateClipping() {
- mClipRect.set(0, mClipTopOptimization, getWidth(), getActualHeight());
+ int top = mClipTopOptimization;
+ if (top >= getActualHeight()) {
+ top = getActualHeight() - 1;
+ }
+ mClipRect.set(0, top, getWidth(), getActualHeight());
setClipBounds(mClipRect);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 6627360..8e5d4d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -644,6 +644,16 @@
}
@Override
+ public void onScreenTurnedOn() {
+ mLockIcon.setScreenOn(true);
+ }
+
+ @Override
+ public void onScreenTurnedOff() {
+ mLockIcon.setScreenOn(false);
+ }
+
+ @Override
public void onKeyguardVisibilityChanged(boolean showing) {
mLockIcon.update();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 06d2fca..463abfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -34,12 +34,6 @@
*/
public class LockIcon extends KeyguardAffordanceView {
- /**
- * Delay animations a bit when the screen just turned on as a heuristic to start them after
- * the screen has actually turned on.
- */
- private static final long ANIM_DELAY_AFTER_SCREEN_ON = 250;
-
private static final int STATE_LOCKED = 0;
private static final int STATE_LOCK_OPEN = 1;
private static final int STATE_FACE_UNLOCK = 2;
@@ -50,6 +44,8 @@
private boolean mLastDeviceInteractive;
private boolean mTransientFpError;
private boolean mDeviceInteractive;
+ private boolean mScreenOn;
+ private boolean mLastScreenOn;
private final TrustDrawable mTrustDrawable;
private final UnlockMethodCache mUnlockMethodCache;
private AccessibilityController mAccessibilityController;
@@ -88,6 +84,11 @@
update();
}
+ public void setScreenOn(boolean screenOn) {
+ mScreenOn = screenOn;
+ update();
+ }
+
public void update() {
boolean visible = isShown()
&& KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
@@ -96,20 +97,20 @@
} else {
mTrustDrawable.stop();
}
- if (!visible) {
- return;
- }
// TODO: Real icon for facelock.
int state = getState();
boolean anyFingerprintIcon = state == STATE_FINGERPRINT || state == STATE_FINGERPRINT_ERROR;
- if (state != mLastState || mDeviceInteractive != mLastDeviceInteractive) {
+ if (state != mLastState || mDeviceInteractive != mLastDeviceInteractive
+ || mScreenOn != mLastScreenOn) {
+ boolean isAnim = true;
int iconRes = getAnimationResForTransition(mLastState, state, mLastDeviceInteractive,
- mDeviceInteractive);
+ mDeviceInteractive, mLastScreenOn, mScreenOn);
if (iconRes == R.drawable.lockscreen_fingerprint_draw_off_animation) {
anyFingerprintIcon = true;
}
if (iconRes == -1) {
- iconRes = getIconForState(state);
+ iconRes = getIconForState(state, mScreenOn, mDeviceInteractive);
+ isAnim = false;
}
Drawable icon = mContext.getDrawable(iconRes);
final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
@@ -135,23 +136,12 @@
: R.string.accessibility_unlock_button);
setContentDescription(contentDescription);
mHasFingerPrintIcon = anyFingerprintIcon;
- if (animation != null) {
-
- // If we play the draw on animation, delay it by one frame when the screen is
- // actually turned on.
- if (iconRes == R.drawable.lockscreen_fingerprint_draw_on_animation) {
- postOnAnimationDelayed(new Runnable() {
- @Override
- public void run() {
- animation.start();
- }
- }, ANIM_DELAY_AFTER_SCREEN_ON);
- } else {
- animation.start();
- }
+ if (animation != null && isAnim) {
+ animation.start();
}
mLastState = state;
mLastDeviceInteractive = mDeviceInteractive;
+ mLastScreenOn = mScreenOn;
}
// Hide trust circle when fingerprint is running.
@@ -192,7 +182,7 @@
mAccessibilityController = accessibilityController;
}
- private int getIconForState(int state) {
+ private int getIconForState(int state, boolean screenOn, boolean deviceInteractive) {
switch (state) {
case STATE_LOCKED:
return R.drawable.ic_lock_24dp;
@@ -201,7 +191,11 @@
case STATE_FACE_UNLOCK:
return com.android.internal.R.drawable.ic_account_circle;
case STATE_FINGERPRINT:
- return R.drawable.ic_fingerprint;
+ // If screen is off and device asleep, use the draw on animation so the first frame
+ // gets drawn.
+ return screenOn && deviceInteractive
+ ? R.drawable.ic_fingerprint
+ : R.drawable.lockscreen_fingerprint_draw_on_animation;
case STATE_FINGERPRINT_ERROR:
return R.drawable.ic_fingerprint_error;
default:
@@ -209,8 +203,9 @@
}
}
- private int getAnimationResForTransition(int oldState, int newState, boolean oldScreenOn,
- boolean screenOn) {
+ private int getAnimationResForTransition(int oldState, int newState,
+ boolean oldDeviceInteractive, boolean deviceInteractive,
+ boolean oldScreenOn, boolean screenOn) {
if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
return R.drawable.lockscreen_fingerprint_fp_to_error_state_animation;
} else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
@@ -218,7 +213,8 @@
} else if (oldState == STATE_FINGERPRINT && newState == STATE_LOCK_OPEN
&& !mUnlockMethodCache.isTrusted()) {
return R.drawable.lockscreen_fingerprint_draw_off_animation;
- } else if (newState == STATE_FINGERPRINT && !oldScreenOn && screenOn) {
+ } else if (newState == STATE_FINGERPRINT && (!oldScreenOn && screenOn && deviceInteractive
+ || screenOn && !oldDeviceInteractive && deviceInteractive)) {
return R.drawable.lockscreen_fingerprint_draw_on_animation;
} else {
return -1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 5d2e5b7..82064a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -413,7 +413,9 @@
ExpandableNotificationRow topHeadsUpEntry = ambientState.getTopHeadsUpEntry();
int childCount = algorithmState.visibleChildren.size();
- int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
+ int numberOfElementsCompletelyIn = algorithmState.partialInTop == 1.0f
+ ? algorithmState.lastTopStackIndex
+ : (int) algorithmState.itemsInTopStack;
for (int i = 0; i < childCount; i++) {
ExpandableView child = algorithmState.visibleChildren.get(i);
StackViewState childViewState = resultState.getViewStateForView(child);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 417f18d..ec02789 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -32,6 +32,7 @@
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -56,15 +57,18 @@
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.Xml;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.os.Zygote;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
+import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -98,19 +102,38 @@
}
};
- final SparseArray<HashMap<String, Ops>> mUidOps
- = new SparseArray<HashMap<String, Ops>>();
+ final SparseArray<UidState> mUidStates = new SparseArray<>();
private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>();
+ private static final class UidState {
+ public final int uid;
+ public ArrayMap<String, Ops> pkgOps;
+ public SparseIntArray opModes;
+
+ public UidState(int uid) {
+ this.uid = uid;
+ }
+
+ public void clear() {
+ pkgOps = null;
+ opModes = null;
+ }
+
+ public boolean isDefault() {
+ return (pkgOps == null || pkgOps.isEmpty())
+ && (opModes == null || opModes.size() <= 0);
+ }
+ }
+
public final static class Ops extends SparseArray<Op> {
public final String packageName;
- public final int uid;
+ public final UidState uidState;
public final boolean isPrivileged;
- public Ops(String _packageName, int _uid, boolean _isPrivileged) {
+ public Ops(String _packageName, UidState _uidState, boolean _isPrivileged) {
packageName = _packageName;
- uid = _uid;
+ uidState = _uidState;
isPrivileged = _isPrivileged;
}
}
@@ -220,27 +243,42 @@
public void systemReady() {
synchronized (this) {
boolean changed = false;
- for (int i=0; i<mUidOps.size(); i++) {
- HashMap<String, Ops> pkgs = mUidOps.valueAt(i);
+ for (int i = mUidStates.size() - 1; i >= 0; i--) {
+ UidState uidState = mUidStates.valueAt(i);
+
+ String[] packageNames = getPackagesForUid(uidState.uid);
+ if (ArrayUtils.isEmpty(packageNames)) {
+ uidState.clear();
+ mUidStates.removeAt(i);
+ changed = true;
+ continue;
+ }
+
+ ArrayMap<String, Ops> pkgs = uidState.pkgOps;
+ if (pkgs == null) {
+ continue;
+ }
+
Iterator<Ops> it = pkgs.values().iterator();
while (it.hasNext()) {
Ops ops = it.next();
int curUid;
try {
curUid = mContext.getPackageManager().getPackageUid(ops.packageName,
- UserHandle.getUserId(ops.uid));
+ UserHandle.getUserId(ops.uidState.uid));
} catch (NameNotFoundException e) {
curUid = -1;
}
- if (curUid != ops.uid) {
+ if (curUid != ops.uidState.uid) {
Slog.i(TAG, "Pruning old package " + ops.packageName
- + "/" + ops.uid + ": new uid=" + curUid);
+ + "/" + ops.uidState + ": new uid=" + curUid);
it.remove();
changed = true;
}
}
- if (pkgs.size() <= 0) {
- mUidOps.removeAt(i);
+
+ if (uidState.isDefault()) {
+ mUidStates.removeAt(i);
}
}
if (changed) {
@@ -279,22 +317,34 @@
public void packageRemoved(int uid, String packageName) {
synchronized (this) {
- HashMap<String, Ops> pkgs = mUidOps.get(uid);
- if (pkgs != null) {
- if (pkgs.remove(packageName) != null) {
- if (pkgs.size() <= 0) {
- mUidOps.remove(uid);
- }
- scheduleFastWriteLocked();
- }
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null) {
+ return;
+ }
+
+ boolean changed = false;
+
+ // Remove any package state if such.
+ if (uidState.pkgOps != null && uidState.pkgOps.remove(packageName) != null) {
+ changed = true;
+ }
+
+ // If we just nuked the last package state check if the UID is valid.
+ if (changed && uidState.pkgOps.isEmpty()
+ && getPackagesForUid(uid).length <= 0) {
+ mUidStates.remove(uid);
+ }
+
+ if (changed) {
+ scheduleFastWriteLocked();
}
}
}
public void uidRemoved(int uid) {
synchronized (this) {
- if (mUidOps.indexOfKey(uid) >= 0) {
- mUidOps.remove(uid);
+ if (mUidStates.indexOfKey(uid) >= 0) {
+ mUidStates.remove(uid);
scheduleFastWriteLocked();
}
}
@@ -346,16 +396,23 @@
Binder.getCallingPid(), Binder.getCallingUid(), null);
ArrayList<AppOpsManager.PackageOps> res = null;
synchronized (this) {
- for (int i=0; i<mUidOps.size(); i++) {
- HashMap<String, Ops> packages = mUidOps.valueAt(i);
- for (Ops pkgOps : packages.values()) {
+ final int uidStateCount = mUidStates.size();
+ for (int i = 0; i < uidStateCount; i++) {
+ UidState uidState = mUidStates.valueAt(i);
+ if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) {
+ continue;
+ }
+ ArrayMap<String, Ops> packages = uidState.pkgOps;
+ final int packageCount = packages.size();
+ for (int j = 0; j < packageCount; j++) {
+ Ops pkgOps = packages.valueAt(j);
ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
if (resOps != null) {
if (res == null) {
res = new ArrayList<AppOpsManager.PackageOps>();
}
AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
- pkgOps.packageName, pkgOps.uid, resOps);
+ pkgOps.packageName, pkgOps.uidState.uid, resOps);
res.add(resPackage);
}
}
@@ -380,7 +437,7 @@
}
ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
- pkgOps.packageName, pkgOps.uid, resOps);
+ pkgOps.packageName, pkgOps.uidState.uid, resOps);
res.add(resPackage);
return res;
}
@@ -392,11 +449,15 @@
if (ops != null) {
ops.remove(op.op);
if (ops.size() <= 0) {
- HashMap<String, Ops> pkgOps = mUidOps.get(uid);
+ UidState uidState = ops.uidState;
+ ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
if (pkgOps != null) {
pkgOps.remove(ops.packageName);
- if (pkgOps.size() <= 0) {
- mUidOps.remove(uid);
+ if (pkgOps.isEmpty()) {
+ uidState.pkgOps = null;
+ }
+ if (uidState.isDefault()) {
+ mUidStates.remove(uid);
}
}
}
@@ -405,6 +466,113 @@
}
@Override
+ public void setUidMode(int code, int uid, int mode) {
+ if (Binder.getCallingPid() != Process.myPid()) {
+ mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ }
+ verifyIncomingOp(code);
+ code = AppOpsManager.opToSwitch(code);
+
+ synchronized (this) {
+ final int defaultMode = AppOpsManager.opToDefaultMode(code);
+
+ UidState uidState = getUidStateLocked(uid, false);
+ if (uidState == null) {
+ if (mode == defaultMode) {
+ return;
+ }
+ uidState = new UidState(uid);
+ uidState.opModes = new SparseIntArray();
+ uidState.opModes.put(code, mode);
+ mUidStates.put(uid, uidState);
+ scheduleWriteLocked();
+ } else if (uidState.opModes == null) {
+ if (mode != defaultMode) {
+ uidState.opModes = new SparseIntArray();
+ uidState.opModes.put(code, mode);
+ scheduleWriteLocked();
+ }
+ } else {
+ if (uidState.opModes.get(code) == mode) {
+ return;
+ }
+ if (mode == defaultMode) {
+ uidState.opModes.delete(code);
+ if (uidState.opModes.size() <= 0) {
+ uidState.opModes = null;
+ }
+ } else {
+ uidState.opModes.put(code, mode);
+ }
+ scheduleWriteLocked();
+ }
+ }
+
+ ArrayMap<Callback, ArraySet<String>> callbackSpecs = null;
+
+ ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
+ if (callbacks != null) {
+ final int callbackCount = callbacks.size();
+ for (int i = 0; i < callbackCount; i++) {
+ Callback callback = callbacks.get(i);
+ callbackSpecs = new ArrayMap<>();
+ callbackSpecs.put(callback, null);
+ }
+ }
+
+ String[] uidPackageNames = getPackagesForUid(uid);
+ for (String uidPackageName : uidPackageNames) {
+ callbacks = mPackageModeWatchers.get(uidPackageName);
+ if (callbacks != null) {
+ if (callbackSpecs == null) {
+ callbackSpecs = new ArrayMap<>();
+ }
+ final int callbackCount = callbacks.size();
+ for (int i = 0; i < callbackCount; i++) {
+ Callback callback = callbacks.get(i);
+ ArraySet<String> changedPackages = callbackSpecs.get(callback);
+ if (changedPackages == null) {
+ changedPackages = new ArraySet<>();
+ callbackSpecs.put(callback, changedPackages);
+ }
+ changedPackages.add(uidPackageName);
+ }
+ }
+ }
+
+ if (callbackSpecs == null) {
+ return;
+ }
+
+ // There are components watching for mode changes such as window manager
+ // and location manager which are in our process. The callbacks in these
+ // components may require permissions our remote caller does not have.
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (int i = 0; i < callbackSpecs.size(); i++) {
+ Callback callback = callbackSpecs.keyAt(i);
+ ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
+ try {
+ if (reportedPackageNames == null) {
+ callback.mCallback.opChanged(code, null);
+ } else {
+ final int reportedPackageCount = reportedPackageNames.size();
+ for (int j = 0; j < reportedPackageCount; j++) {
+ String reportedPackageName = reportedPackageNames.valueAt(j);
+ callback.mCallback.opChanged(code, reportedPackageName);
+ }
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error dispatching op op change", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void setMode(int code, int uid, String packageName, int mode) {
if (Binder.getCallingPid() != Process.myPid()) {
mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
@@ -414,6 +582,7 @@
ArrayList<Callback> repCbs = null;
code = AppOpsManager.opToSwitch(code);
synchronized (this) {
+ UidState uidState = getUidStateLocked(uid, false);
Op op = getOpLocked(code, uid, packageName, true);
if (op != null) {
if (op.mode != mode) {
@@ -468,14 +637,26 @@
if (callbacks == null) {
callbacks = new HashMap<Callback, ArrayList<Pair<String, Integer>>>();
}
+ boolean duplicate = false;
for (int i=0; i<cbs.size(); i++) {
Callback cb = cbs.get(i);
ArrayList<Pair<String, Integer>> reports = callbacks.get(cb);
if (reports == null) {
reports = new ArrayList<Pair<String, Integer>>();
callbacks.put(cb, reports);
+ } else {
+ final int reportCount = reports.size();
+ for (int j = 0; j < reportCount; j++) {
+ Pair<String, Integer> report = reports.get(j);
+ if (report.second == op && report.first.equals(packageName)) {
+ duplicate = true;
+ break;
+ }
+ }
}
- reports.add(new Pair<String, Integer>(packageName, op));
+ if (!duplicate) {
+ reports.add(new Pair<>(packageName, op));
+ }
}
return callbacks;
}
@@ -488,16 +669,54 @@
callingPid, callingUid, null);
reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
true, true, "resetAllModes", null);
+
+ int reqUid = -1;
+ if (reqPackageName != null) {
+ try {
+ reqUid = AppGlobals.getPackageManager().getPackageUid(
+ reqPackageName, reqUserId);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
+ }
+
HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks = null;
synchronized (this) {
boolean changed = false;
- for (int i=mUidOps.size()-1; i>=0; i--) {
- HashMap<String, Ops> packages = mUidOps.valueAt(i);
+ for (int i = mUidStates.size() - 1; i >= 0; i--) {
+ UidState uidState = mUidStates.valueAt(i);
+
+ SparseIntArray opModes = uidState.opModes;
+ if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
+ final int uidOpCount = opModes.size();
+ for (int j = uidOpCount - 1; j >= 0; j--) {
+ final int code = opModes.keyAt(j);
+ if (AppOpsManager.opAllowsReset(code)) {
+ opModes.removeAt(j);
+ if (opModes.size() <= 0) {
+ uidState.opModes = null;
+ }
+ for (String packageName : getPackagesForUid(uidState.uid)) {
+ callbacks = addCallbacks(callbacks, packageName, code,
+ mOpModeWatchers.get(code));
+ callbacks = addCallbacks(callbacks, packageName, code,
+ mPackageModeWatchers.get(packageName));
+ }
+ }
+ }
+ }
+
+ if (uidState.pkgOps == null) {
+ continue;
+ }
+
if (reqUserId != UserHandle.USER_ALL
- && reqUserId != UserHandle.getUserId(mUidOps.keyAt(i))) {
+ && reqUserId != UserHandle.getUserId(uidState.uid)) {
// Skip any ops for a different user
continue;
}
+
+ Map<String, Ops> packages = uidState.pkgOps;
Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Ops> ent = it.next();
@@ -526,10 +745,11 @@
it.remove();
}
}
- if (packages.size() == 0) {
- mUidOps.removeAt(i);
+ if (uidState.isDefault()) {
+ mUidStates.remove(uidState.uid);
}
}
+
if (changed) {
scheduleFastWriteLocked();
}
@@ -552,7 +772,7 @@
@Override
public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
synchronized (this) {
- op = AppOpsManager.opToSwitch(op);
+ op = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op;
Callback cb = mModeWatchers.get(callback.asBinder());
if (cb == null) {
cb = new Callback(callback);
@@ -621,7 +841,15 @@
if (isOpRestricted(uid, code, packageName)) {
return AppOpsManager.MODE_IGNORED;
}
- Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
+ code = AppOpsManager.opToSwitch(code);
+ UidState uidState = getUidStateLocked(uid, false);
+ if (uidState != null && uidState.opModes != null) {
+ final int uidMode = uidState.opModes.get(code);
+ if (uidMode != AppOpsManager.MODE_ALLOWED) {
+ return uidMode;
+ }
+ }
+ Op op = getOpLocked(code, uid, packageName, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -732,6 +960,17 @@
}
op.duration = 0;
final int switchCode = AppOpsManager.opToSwitch(code);
+ UidState uidState = ops.uidState;
+ if (uidState.opModes != null) {
+ final int uidMode = uidState.opModes.get(switchCode);
+ if (uidMode != AppOpsManager.MODE_ALLOWED) {
+ if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+ + switchCode + " (" + code + ") uid " + uid + " package "
+ + packageName);
+ op.rejectTime = System.currentTimeMillis();
+ return uidMode;
+ }
+ }
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
@@ -766,6 +1005,17 @@
return AppOpsManager.MODE_IGNORED;
}
final int switchCode = AppOpsManager.opToSwitch(code);
+ UidState uidState = ops.uidState;
+ if (uidState.opModes != null) {
+ final int uidMode = uidState.opModes.get(switchCode);
+ if (uidMode != AppOpsManager.MODE_ALLOWED) {
+ if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+ + switchCode + " (" + code + ") uid " + uid + " package "
+ + packageName);
+ op.rejectTime = System.currentTimeMillis();
+ return uidMode;
+ }
+ }
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
@@ -847,6 +1097,18 @@
throw new IllegalArgumentException("Bad operation #" + op);
}
+ private UidState getUidStateLocked(int uid, boolean edit) {
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null) {
+ if (!edit) {
+ return null;
+ }
+ uidState = new UidState(uid);
+ mUidStates.put(uid, uidState);
+ }
+ return uidState;
+ }
+
private Ops getOpsLocked(int uid, String packageName, boolean edit) {
if (uid == 0) {
packageName = "root";
@@ -857,15 +1119,19 @@
}
private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
- HashMap<String, Ops> pkgOps = mUidOps.get(uid);
- if (pkgOps == null) {
+ UidState uidState = getUidStateLocked(uid, edit);
+ if (uidState == null) {
+ return null;
+ }
+
+ if (uidState.pkgOps == null) {
if (!edit) {
return null;
}
- pkgOps = new HashMap<String, Ops>();
- mUidOps.put(uid, pkgOps);
+ uidState.pkgOps = new ArrayMap<>();
}
- Ops ops = pkgOps.get(packageName);
+
+ Ops ops = uidState.pkgOps.get(packageName);
if (ops == null) {
if (!edit) {
return null;
@@ -904,8 +1170,8 @@
Binder.restoreCallingIdentity(ident);
}
}
- ops = new Ops(packageName, uid, isPrivileged);
- pkgOps.put(packageName, ops);
+ ops = new Ops(packageName, uidState, isPrivileged);
+ uidState.pkgOps.put(packageName, ops);
}
return ops;
}
@@ -940,7 +1206,7 @@
if (!edit) {
return null;
}
- op = new Op(ops.uid, ops.packageName, code);
+ op = new Op(ops.uidState.uid, ops.packageName, code);
ops.put(code, op);
}
if (edit) {
@@ -1000,6 +1266,8 @@
String tagName = parser.getName();
if (tagName.equals("pkg")) {
readPackage(parser);
+ } if (tagName.equals("uid")) {
+ readUidOps(parser);
} else {
Slog.w(TAG, "Unknown element under <app-ops>: "
+ parser.getName());
@@ -1021,7 +1289,7 @@
Slog.w(TAG, "Failed parsing " + e);
} finally {
if (!success) {
- mUidOps.clear();
+ mUidStates.clear();
}
try {
stream.close();
@@ -1032,6 +1300,34 @@
}
}
+ void readUidOps(XmlPullParser parser) throws NumberFormatException,
+ XmlPullParserException, IOException {
+ final int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("op")) {
+ final int code = Integer.parseInt(parser.getAttributeValue(null, "n"));
+ final int mode = Integer.parseInt(parser.getAttributeValue(null, "m"));
+ UidState uidState = getUidStateLocked(uid, true);
+ if (uidState.opModes == null) {
+ uidState.opModes = new SparseIntArray();
+ }
+ uidState.opModes.put(code, mode);
+ } else {
+ Slog.w(TAG, "Unknown element under <uid-ops>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ }
+
void readPackage(XmlPullParser parser) throws NumberFormatException,
XmlPullParserException, IOException {
String pkgName = parser.getAttributeValue(null, "n");
@@ -1114,15 +1410,16 @@
if (proxyPackageName != null) {
op.proxyPackageName = proxyPackageName;
}
- HashMap<String, Ops> pkgOps = mUidOps.get(uid);
- if (pkgOps == null) {
- pkgOps = new HashMap<String, Ops>();
- mUidOps.put(uid, pkgOps);
+
+ UidState uidState = getUidStateLocked(uid, true);
+ if (uidState.pkgOps == null) {
+ uidState.pkgOps = new ArrayMap<>();
}
- Ops ops = pkgOps.get(pkgName);
+
+ Ops ops = uidState.pkgOps.get(pkgName);
if (ops == null) {
- ops = new Ops(pkgName, uid, isPrivileged);
- pkgOps.put(pkgName, ops);
+ ops = new Ops(pkgName, uidState, isPrivileged);
+ uidState.pkgOps.put(pkgName, ops);
}
ops.put(op.op, op);
} else {
@@ -1149,7 +1446,27 @@
XmlSerializer out = new FastXmlSerializer();
out.setOutput(stream, StandardCharsets.UTF_8.name());
out.startDocument(null, true);
- out.startTag(null, "app-ops");
+ out.startTag(null, "app");
+
+ final int uidStateCount = mUidStates.size();
+ for (int i = 0; i < uidStateCount; i++) {
+ UidState uidState = mUidStates.valueAt(i);
+ if (uidState.opModes != null && uidState.opModes.size() > 0) {
+ out.startTag(null, "uid");
+ out.attribute(null, "n", Integer.toString(uidState.uid));
+ SparseIntArray uidOpModes = uidState.opModes;
+ final int opCount = uidOpModes.size();
+ for (int j = 0; j < opCount; j++) {
+ final int op = uidOpModes.keyAt(j);
+ final int mode = uidOpModes.valueAt(j);
+ out.startTag(null, "op");
+ out.attribute(null, "n", Integer.toString(op));
+ out.attribute(null, "m", Integer.toString(mode));
+ out.endTag(null, "op");
+ }
+ out.endTag(null, "uid");
+ }
+ }
if (allOps != null) {
String lastPkg = null;
@@ -1316,9 +1633,27 @@
if (needSep) {
pw.println();
}
- for (int i=0; i<mUidOps.size(); i++) {
- pw.print(" Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
- HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
+ for (int i=0; i<mUidStates.size(); i++) {
+ UidState uidState = mUidStates.valueAt(i);
+
+ pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
+
+ SparseIntArray opModes = uidState.opModes;
+ if (opModes != null) {
+ final int opModeCount = opModes.size();
+ for (int j = 0; j < opModeCount; j++) {
+ final int code = opModes.keyAt(j);
+ final int mode = opModes.valueAt(j);
+ pw.print(" "); pw.print(AppOpsManager.opToName(code));
+ pw.print(": mode="); pw.println(mode);
+ }
+ }
+
+ ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
+ if (pkgOps == null) {
+ continue;
+ }
+
for (Ops ops : pkgOps.values()) {
pw.print(" Package "); pw.print(ops.packageName); pw.println(":");
for (int j=0; j<ops.size(); j++) {
@@ -1382,4 +1717,12 @@
}
}
+ private static String[] getPackagesForUid(int uid) {
+ try {
+ return AppGlobals.getPackageManager().getPackagesForUid(uid);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
+ return EmptyArray.STRING;
+ }
}
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index d7b0765..e17ff5c 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -32,6 +32,7 @@
import android.os.PowerManager.WakeLock;
import android.os.SystemProperties;
import android.provider.MediaStore;
+import android.provider.Settings;
import android.util.Slog;
/**
@@ -152,13 +153,25 @@
private void handleCameraLaunchGesture() {
if (DBG) Slog.d(TAG, "Received a camera launch event.");
+ boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
+ if (!userSetupComplete) {
+ if (DBG) Slog.d(TAG, String.format(
+ "userSetupComplete = %s, ignoring camera launch gesture.",
+ userSetupComplete));
+ return;
+ }
+ if (DBG) Slog.d(TAG, String.format(
+ "userSetupComplete = %s, performing camera launch gesture.",
+ userSetupComplete));
boolean locked = mKeyGuard != null && mKeyGuard.inKeyguardRestrictedInputMode();
String action = locked
? MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
: MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA;
Intent intent = new Intent(action);
PackageManager pm = mContext.getPackageManager();
- ResolveInfo componentInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ ResolveInfo componentInfo = pm.resolveActivity(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
if (componentInfo == null) {
if (DBG) Slog.d(TAG, "Couldn't find an app to process the camera intent.");
return;
@@ -167,7 +180,6 @@
if (mVibrator != null && mVibrator.hasVibrator()) {
mVibrator.vibrate(1000L);
}
-
// Turn on the screen before the camera launches.
mWakeLock.acquire(500L);
intent.setComponent(new ComponentName(componentInfo.activityInfo.packageName,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 95cbf10..a7cd9ff 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1257,7 +1257,11 @@
}
for (int stream = 0; stream < mStreamStates.length; stream++) {
if (streamTypeAlias == mStreamVolumeAlias[stream]) {
- mStreamStates[stream].mute(state);
+ if (!(readCameraSoundForced()
+ && (mStreamStates[stream].getStreamType()
+ == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
+ mStreamStates[stream].mute(state);
+ }
}
}
} else if ((direction == AudioManager.ADJUST_RAISE) &&
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ba46f4c..4479a37 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8604,7 +8604,7 @@
if (!allowed) {
if (!allowed && (bp.protectionLevel
& PermissionInfo.PROTECTION_FLAG_PRE23) != 0
- && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.MNC) {
+ && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
// If this was a previously normal/dangerous permission that got moved
// to a system permission as part of the runtime permission redesign, then
// we still want to blindly grant it to old apps.
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index a57463c..7bd0635 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -559,6 +559,7 @@
set.addAnimation(clipAnimTB);
set.addAnimation(translateY);
set.addAnimation(alpha);
+ set.setZAdjustment(Animation.ZORDER_TOP);
set.initialize(appWidth, appHeight, appWidth, appHeight);
anim = set;
} else {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 68bc773..af21eb3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2657,6 +2657,16 @@
return disabled;
}
+ boolean isSecureLocked(WindowState w) {
+ if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+ return true;
+ }
+ if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Set mScreenCaptureDisabled for specific user
*/
@@ -3168,6 +3178,9 @@
boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
&& (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
+ if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceControl != null) {
+ winAnimator.mSurfaceControl.setSecure(isSecureLocked(win));
+ }
win.mRelayoutCalled = true;
final int oldVisibility = win.mViewVisibility;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 31ee869..48f2a9d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -785,11 +785,7 @@
int flags = SurfaceControl.HIDDEN;
final WindowManager.LayoutParams attrs = w.mAttrs;
- if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
- flags |= SurfaceControl.SECURE;
- }
-
- if (mService.isScreenCaptureDisabledLocked(UserHandle.getUserId(mWin.mOwnerUid))) {
+ if (mService.isSecureLocked(w)) {
flags |= SurfaceControl.SECURE;
}
@@ -1274,6 +1270,7 @@
if (displayContent == null) {
return;
}
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
// Need to recompute a new system decor rect each time.
if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
@@ -1283,7 +1280,6 @@
} else if (!w.isDefaultDisplay()) {
// On a different display there is no system decor. Crop the window
// by the screen boundaries.
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
w.mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top,
displayInfo.logicalWidth - w.mCompatFrame.left,
@@ -1305,9 +1301,11 @@
applyDecorRect(w.mDecorFrame);
}
- // By default, the clip rect is the system decor if the transformation doesn't specify one.
+ final boolean fullscreen = w.isFullscreen(displayInfo.appWidth, displayInfo.appHeight);
final Rect clipRect = mTmpClipRect;
- clipRect.set((mHasClipRect) ? mClipRect : w.mSystemDecorRect);
+ // We use the clip rect as provided by the tranformation for non-fullscreen windows to
+ // avoid premature clipping with the system decor rect.
+ clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : w.mSystemDecorRect);
// Expand the clip rect for surface insets.
final WindowManager.LayoutParams attrs = w.mAttrs;
@@ -1316,6 +1314,13 @@
clipRect.right += attrs.surfaceInsets.right;
clipRect.bottom += attrs.surfaceInsets.bottom;
+ if (mHasClipRect && fullscreen) {
+ // We intersect the clip rect specified by the transformation with the expanded system
+ // decor rect to prevent artifacts from drawing during animation if the transformation
+ // clip rect extends outside the system decor rect.
+ clipRect.intersect(mClipRect);
+ }
+
// The clip rect was generated assuming (0,0) as the window origin,
// so we need to translate to match the actual surface coordinates.
clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1e833b1..cd2885b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -6436,7 +6436,7 @@
final ApplicationInfo ai = AppGlobals.getPackageManager()
.getApplicationInfo(packageName, 0, user.getIdentifier());
final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
- if (targetSdkVersion < android.os.Build.VERSION_CODES.MNC) {
+ if (targetSdkVersion < android.os.Build.VERSION_CODES.M) {
return false;
}
final PackageManager packageManager = mContext.getPackageManager();
diff --git a/tests/VoiceInteraction/res/layout/main.xml b/tests/VoiceInteraction/res/layout/main.xml
index 0f968eb..a83d02c 100644
--- a/tests/VoiceInteraction/res/layout/main.xml
+++ b/tests/VoiceInteraction/res/layout/main.xml
@@ -26,6 +26,12 @@
android:text="@string/start"
/>
+ <CheckBox android:id="@+id/secure"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/secure"
+ />
+
<com.android.test.voiceinteraction.AsyncStructure
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/tests/VoiceInteraction/res/values/strings.xml b/tests/VoiceInteraction/res/values/strings.xml
index ab39f99..29ffe21 100644
--- a/tests/VoiceInteraction/res/values/strings.xml
+++ b/tests/VoiceInteraction/res/values/strings.xml
@@ -17,6 +17,7 @@
<resources>
<string name="start">Start</string>
+ <string name="secure">Secure</string>
<string name="tree">Tree</string>
<string name="text">Text</string>
<string name="asyncStructure">(Async structure goes here)</string>
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/VoiceInteractionMain.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/VoiceInteractionMain.java
index ee75f28..87fa91a 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/VoiceInteractionMain.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/VoiceInteractionMain.java
@@ -21,6 +21,8 @@
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
+import android.view.WindowManager;
+import android.widget.CheckBox;
public class VoiceInteractionMain extends Activity {
@@ -30,6 +32,7 @@
setContentView(R.layout.main);
findViewById(R.id.start).setOnClickListener(mStartListener);
+ findViewById(R.id.secure).setOnClickListener(mSecureListener);
}
@Override
@@ -52,4 +55,14 @@
showAssist(null);
}
};
+
+ View.OnClickListener mSecureListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ if (((CheckBox)v).isChecked()) {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ } else {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ }
+ }
+ };
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
index 645634f..09937bc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
@@ -74,7 +74,7 @@
}
public static String getTime(int platformVersion) {
- if (isGreaterOrEqual(platformVersion, MNC)) {
+ if (isGreaterOrEqual(platformVersion, M)) {
return "6:00";
}
if (platformVersion < GINGERBREAD) {
@@ -95,7 +95,7 @@
if (platformVersion < LOLLIPOP_MR1) {
return "5:00";
}
- if (platformVersion < MNC) {
+ if (platformVersion < M) {
return "5:10";
}
// Should never happen.
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index d915e5d..cf88df4 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -669,6 +669,7 @@
try {
return mService.getConfiguredNetworks();
} catch (RemoteException e) {
+ Log.w(TAG, "Caught RemoteException trying to get configured networks: " + e);
return null;
}
}
@@ -1589,6 +1590,7 @@
try {
return mService.buildWifiConfig(uriString, mimeType, data);
} catch (RemoteException e) {
+ Log.w(TAG, "Caught RemoteException trying to build wifi config: " + e);
return null;
}
}