Merge "Fix GamepadTestCase#testButtonA CTS test"
diff --git a/Android.bp b/Android.bp
index 4ab5f1f..5c059b5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -28,26 +28,26 @@
proto: {
type: "full",
},
+ srcs: [
+ "core/proto/**/*.proto",
+ "libs/incident/**/*.proto",
+ ],
},
android: {
proto: {
type: "lite",
},
+ // We only build the protos that are optimized for the lite
+ // runtime, as well as the only protos that are actually
+ // needed by the device.
+ srcs: [
+ "core/proto/android/service/graphicsstats.proto",
+ ],
shared: {
- // The proto files generate full protos, but we only use
- // them as lite on device. This works fine for a static
- // library, where the unused full symbols are stripped,
- // but fails if it is linked as a standalone shared
- // library because it is missing the full runtime.
enabled: false,
},
},
},
-
- srcs: [
- "core/proto/**/*.proto",
- "libs/incident/**/*.proto",
- ],
}
subdirs = [
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f6aea96..5bb54c2 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1700,15 +1700,27 @@
@Override
public int installExistingPackage(String packageName) throws NameNotFoundException {
- return installExistingPackageAsUser(packageName, mContext.getUserId());
+ return installExistingPackage(packageName, PackageManager.INSTALL_REASON_UNKNOWN);
+ }
+
+ @Override
+ public int installExistingPackage(String packageName, int installReason)
+ throws NameNotFoundException {
+ return installExistingPackageAsUser(packageName, installReason, mContext.getUserId());
}
@Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
+ return installExistingPackageAsUser(packageName, PackageManager.INSTALL_REASON_UNKNOWN,
+ userId);
+ }
+
+ private int installExistingPackageAsUser(String packageName, int installReason, int userId)
+ throws NameNotFoundException {
try {
int res = mPM.installExistingPackageAsUser(packageName, userId, 0 /*installFlags*/,
- PackageManager.INSTALL_REASON_UNKNOWN);
+ installReason);
if (res == INSTALL_FAILED_INVALID_URI) {
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ccbd5b4..8a15b1f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -16,6 +16,8 @@
package android.app;
+import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
+
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
@@ -42,7 +44,6 @@
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.BadParcelableException;
-import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -72,6 +73,7 @@
import android.widget.RemoteViews;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.NotificationColorUtil;
import com.android.internal.util.Preconditions;
@@ -2670,6 +2672,19 @@
private static final boolean USE_ONLY_TITLE_IN_LOW_PRIORITY_SUMMARY =
SystemProperties.getBoolean("notifications.only_title", true);
+ /**
+ * The lightness difference that has to be added to the primary text color to obtain the
+ * secondary text color when the background is light.
+ */
+ private static final int LIGHTNESS_TEXT_DIFFERENCE_LIGHT = 20;
+
+ /**
+ * The lightness difference that has to be added to the primary text color to obtain the
+ * secondary text color when the background is dark.
+ * A bit less then the above value, since it looks better on dark backgrounds.
+ */
+ private static final int LIGHTNESS_TEXT_DIFFERENCE_DARK = -10;
+
private Context mContext;
private Notification mN;
private Bundle mUserExtras = new Bundle();
@@ -3836,11 +3851,26 @@
contentView.setTextColor(id, mPrimaryTextColor);
}
- private int getPrimaryTextColor() {
+ /**
+ * @return the primary text color
+ * @hide
+ */
+ @VisibleForTesting
+ public int getPrimaryTextColor() {
ensureColors();
return mPrimaryTextColor;
}
+ /**
+ * @return the secondary text color
+ * @hide
+ */
+ @VisibleForTesting
+ public int getSecondaryTextColor() {
+ ensureColors();
+ return mSecondaryTextColor;
+ }
+
private int getActionBarColor() {
ensureColors();
return mActionBarColor;
@@ -3880,16 +3910,21 @@
double textLum = NotificationColorUtil.calculateLuminance(mForegroundColor);
double contrast = NotificationColorUtil.calculateContrast(mForegroundColor,
backgroundColor);
- boolean textDark = backLum > textLum;
+ // We only respect the given colors if worst case Black or White still has
+ // contrast
+ boolean backgroundLight = backLum > textLum
+ && satisfiesTextContrast(backgroundColor, Color.BLACK)
+ || backLum <= textLum
+ && !satisfiesTextContrast(backgroundColor, Color.WHITE);
if (contrast < 4.5f) {
- if (textDark) {
+ if (backgroundLight) {
mSecondaryTextColor = NotificationColorUtil.findContrastColor(
mForegroundColor,
backgroundColor,
true /* findFG */,
4.5f);
mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
- mSecondaryTextColor, -20);
+ mSecondaryTextColor, -LIGHTNESS_TEXT_DIFFERENCE_LIGHT);
} else {
mSecondaryTextColor =
NotificationColorUtil.findContrastColorAgainstDark(
@@ -3898,16 +3933,17 @@
true /* findFG */,
4.5f);
mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
- mSecondaryTextColor, 10);
+ mSecondaryTextColor, -LIGHTNESS_TEXT_DIFFERENCE_DARK);
}
} else {
mPrimaryTextColor = mForegroundColor;
mSecondaryTextColor = NotificationColorUtil.changeColorLightness(
- mPrimaryTextColor, textDark ? 10 : -20);
+ mPrimaryTextColor, backgroundLight ? LIGHTNESS_TEXT_DIFFERENCE_LIGHT
+ : LIGHTNESS_TEXT_DIFFERENCE_DARK);
if (NotificationColorUtil.calculateContrast(mSecondaryTextColor,
backgroundColor) < 4.5f) {
// oh well the secondary is not good enough
- if (textDark) {
+ if (backgroundLight) {
mSecondaryTextColor = NotificationColorUtil.findContrastColor(
mSecondaryTextColor,
backgroundColor,
@@ -3922,7 +3958,9 @@
4.5f);
}
mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
- mSecondaryTextColor, textDark ? -20 : 10);
+ mSecondaryTextColor, backgroundLight
+ ? -LIGHTNESS_TEXT_DIFFERENCE_LIGHT
+ : -LIGHTNESS_TEXT_DIFFERENCE_DARK);
}
}
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 1d5377b..4889c86 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -656,6 +656,8 @@
void deletePreloadsFileCache();
+ ComponentName getInstantAppResolverComponent();
+
ComponentName getInstantAppResolverSettingsComponent();
ComponentName getInstantAppInstallerComponent();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ca15275..68f0c83 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4666,6 +4666,14 @@
/**
* If there is already an application with the given package name installed
+ * on the system for other users, also install it for the calling user.
+ * @hide
+ */
+ public abstract int installExistingPackage(String packageName, @InstallReason int installReason)
+ throws NameNotFoundException;
+
+ /**
+ * If there is already an application with the given package name installed
* on the system for other users, also install it for the specified user.
* @hide
*/
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index e3e0cc5..f779aeb 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -886,6 +886,11 @@
/**
* Return the max width for icons, in pixels.
+ *
+ * <p> Note that this method returns max width of icon's visible part. Hence, it does not take
+ * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
+ * to function as {@link AcaptiveIconDrawable}, multiply
+ * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
*/
public int getIconMaxWidth() {
try {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index fccc877..8e57e85 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -118,6 +118,15 @@
* @hide
*/
public static final int FINGERPRINT_ERROR_VENDOR = 8;
+
+ /**
+ * The operation was canceled because FINGERPRINT_ERROR_LOCKOUT occurred too many times.
+ * Fingerprint authentication is disabled until the user unlocks with strong authentication
+ * (PIN/Pattern/Password)
+ * @hide
+ */
+ public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9;
+
/**
* @hide
*/
@@ -871,9 +880,11 @@
case MSG_REMOVED:
sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
msg.arg2 /* groupId */);
+ break;
case MSG_ENUMERATED:
sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
msg.arg2 /* groupId */);
+ break;
}
}
@@ -1013,6 +1024,9 @@
return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
case FINGERPRINT_ERROR_LOCKOUT:
return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
+ case FINGERPRINT_ERROR_LOCKOUT_PERMANENT:
+ return mContext.getString(
+ com.android.internal.R.string.fingerprint_error_lockout_permanent);
case FINGERPRINT_ERROR_VENDOR: {
String[] msgArray = mContext.getResources().getStringArray(
com.android.internal.R.array.fingerprint_error_vendor);
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 6c01b36..fa96dd3 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -16,6 +16,8 @@
package android.os;
+import com.android.internal.os.Zygote;
+
import dalvik.annotation.optimization.FastNative;
/**
@@ -94,6 +96,8 @@
// Must be volatile to avoid word tearing.
private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
+ private static int sZygoteDebugFlags = 0;
+
private static native long nativeGetEnabledTags();
private static native void nativeSetAppTracingAllowed(boolean allowed);
private static native void nativeSetTracingEnabled(boolean allowed);
@@ -118,9 +122,10 @@
// The system provides ordering through a priority level. Callbacks made through
// SystemProperties.addChangeCallback currently have a negative priority, while
// our native code is using a priority of zero.
- SystemProperties.addChangeCallback(new Runnable() {
- @Override public void run() {
- cacheEnabledTags();
+ SystemProperties.addChangeCallback(() -> {
+ cacheEnabledTags();
+ if ((sZygoteDebugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
+ traceCounter(TRACE_TAG_ALWAYS, "java_debuggable", 1);
}
});
}
@@ -201,8 +206,9 @@
*
* @hide
*/
- public static void setTracingEnabled(boolean enabled) {
+ public static void setTracingEnabled(boolean enabled, int debugFlags) {
nativeSetTracingEnabled(enabled);
+ sZygoteDebugFlags = debugFlags;
// Setting whether tracing is enabled may change the tags, so we update the cached tags
// here.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f2df7da..7bd3bf6 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.accounts.AccountManager;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
@@ -2129,7 +2130,7 @@
* @return the list of users that were created.
* @hide
*/
- public List<UserInfo> getUsers(boolean excludeDying) {
+ public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
try {
return mService.getUsers(excludeDying);
} catch (RemoteException re) {
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 5f72fc7..290d811 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -624,8 +624,14 @@
return new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(String.format("geo:0,0?q=%s", text)));
case TextClassifier.TYPE_URL:
- if (!text.startsWith("https://") && !text.startsWith("http://")) {
- text = "http://" + text;
+ final String httpPrefix = "http://";
+ final String httpsPrefix = "https://";
+ if (text.toLowerCase().startsWith(httpPrefix)) {
+ text = httpPrefix + text.substring(httpPrefix.length());
+ } else if (text.toLowerCase().startsWith(httpsPrefix)) {
+ text = httpsPrefix + text.substring(httpsPrefix.length());
+ } else {
+ text = httpPrefix + text;
}
return new Intent(Intent.ACTION_VIEW, Uri.parse(text))
.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index bb658c1..1fef7cb 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2016,7 +2016,7 @@
/**
* Asynchronously invalidates an action mode using the TextClassifier.
*/
- private void invalidateActionModeAsync() {
+ void invalidateActionModeAsync() {
getSelectionActionModeHelper().invalidateActionModeAsync();
}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 59fb02d..8464c6e 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1667,32 +1667,17 @@
int anchorHeight, int drawingLocationY, int screenLocationY, int displayFrameTop,
int displayFrameBottom, boolean allowResize) {
final int winOffsetY = screenLocationY - drawingLocationY;
- final int popupScreenTop = outParams.y + winOffsetY;
- final int spaceBelow = displayFrameBottom - popupScreenTop;
- if (popupScreenTop >= 0 && height <= spaceBelow) {
+ final int anchorTopInScreen = outParams.y + winOffsetY;
+ final int spaceBelow = displayFrameBottom - anchorTopInScreen;
+ if (anchorTopInScreen >= 0 && height <= spaceBelow) {
return true;
}
- final int popupScreenBottom;
- if (mOverlapAnchor) {
- // popupScreenTop equals the anchor's top at this point.
- // When shown above the anchor, an overlapping popup's bottom should be aligned with
- // the anchor's bottom.
- popupScreenBottom = popupScreenTop + anchorHeight;
- } else {
- // popupScreenTop equals the anchor's bottom at this point.
- // When shown above the anchor, a non-overlapping popup's bottom is aligned with
- // the anchor's top.
- popupScreenBottom = popupScreenTop - anchorHeight;
- }
- final int spaceAbove = popupScreenBottom - displayFrameTop;
+ final int spaceAbove = anchorTopInScreen - anchorHeight - displayFrameTop;
if (height <= spaceAbove) {
// Move everything up.
if (mOverlapAnchor) {
- // Add one anchorHeight to compensate for the correction made at the start of
- // findDropDownPosition, and another to account for being aligned to the anchor's
- // bottom, not top.
- yOffset += anchorHeight * 2;
+ yOffset += anchorHeight;
}
outParams.y = drawingLocationY - height + yOffset;
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 89182b0..3d54fe7 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -400,6 +400,7 @@
CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
mTextClassifier = Preconditions.checkNotNull(textClassifier);
mText = Preconditions.checkNotNull(text).toString();
+ mLastClassificationText = null; // invalidate.
Preconditions.checkArgument(selectionEnd > selectionStart);
mSelectionStart = selectionStart;
mSelectionEnd = selectionEnd;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1f54c84..77f27d9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1639,12 +1639,21 @@
boolean canInputOrMove = (mMovement != null || getKeyListener() != null);
boolean clickable = canInputOrMove || isClickable();
boolean longClickable = canInputOrMove || isLongClickable();
+ int focusable = getFocusable();
n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
+ case com.android.internal.R.styleable.View_focusable:
+ TypedValue val = new TypedValue();
+ if (a.getValue(attr, val)) {
+ focusable = (val.type == TypedValue.TYPE_INT_BOOLEAN)
+ ? (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE)
+ : val.data;
+ }
+
case com.android.internal.R.styleable.View_clickable:
clickable = a.getBoolean(attr, clickable);
break;
@@ -1656,6 +1665,13 @@
}
a.recycle();
+ // Some apps were relying on the undefined behavior of focusable winning over
+ // focusableInTouchMode != focusable in TextViews if both were specified in XML (usually
+ // when starting with EditText and setting only focusable=false). To keep those apps from
+ // breaking, re-apply the focusable attribute here.
+ if (focusable != getFocusable()) {
+ setFocusable(focusable);
+ }
setClickable(clickable);
setLongClickable(longClickable);
@@ -10756,7 +10772,11 @@
switch (id) {
case ID_SELECT_ALL:
+ final boolean hadSelection = hasSelection();
selectAllText();
+ if (mEditor != null && hadSelection) {
+ mEditor.invalidateActionModeAsync();
+ }
return true;
case ID_UNDO:
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 373f4bb..78566df 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -132,7 +132,7 @@
void noteBleScanStarted(in WorkSource ws);
void noteBleScanStopped(in WorkSource ws);
void noteResetBleScan();
- void noteBleScanResult(in WorkSource ws);
+ void noteBleScanResults(in WorkSource ws, int numNewResults);
HealthStatsParceler takeUidSnapshot(int uid);
HealthStatsParceler[] takeUidSnapshots(in int[] uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5c6a1b2..20cc419 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -936,6 +936,10 @@
mCount.incrementAndGet();
}
+ void addAtomic(int delta) {
+ mCount.addAndGet(delta);
+ }
+
/**
* Clear state of this counter.
*/
@@ -4842,11 +4846,11 @@
}
}
- public void noteBluetoothScanResultFromSourceLocked(WorkSource ws) {
+ public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
final int N = ws.size();
for (int i = 0; i < N; i++) {
int uid = mapUid(ws.get(i));
- getUidStatsLocked(uid).noteBluetoothScanResultLocked();
+ getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
}
}
@@ -6057,8 +6061,8 @@
return mBluetoothScanResultCounter;
}
- public void noteBluetoothScanResultLocked() {
- createBluetoothScanResultCounterLocked().stepAtomic();
+ public void noteBluetoothScanResultsLocked(int numNewResults) {
+ createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
}
@Override
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index e065843..5eca496 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -107,7 +107,7 @@
fdsToIgnore, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
- Trace.setTracingEnabled(true);
+ Trace.setTracingEnabled(true, debugFlags);
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -152,7 +152,7 @@
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
- Trace.setTracingEnabled(true);
+ Trace.setTracingEnabled(true, debugFlags);
}
VM_HOOKS.postForkCommon();
return pid;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 4ce6ec5..9e61a99 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -745,7 +745,7 @@
bootTimingsTraceLog.traceEnd(); // ZygoteInit
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
- Trace.setTracingEnabled(false);
+ Trace.setTracingEnabled(false, 0);
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index cd41f9e..1ba92bf 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -533,6 +533,10 @@
return ColorUtilsFromCompat.calculateContrast(foregroundColor, backgroundColor);
}
+ public static boolean satisfiesTextContrast(int backgroundColor, int foregroundColor) {
+ return NotificationColorUtil.calculateContrast(backgroundColor, foregroundColor) >= 4.5;
+ }
+
/**
* Composite two potentially translucent colors over each other and returns the result.
*/
@@ -540,6 +544,10 @@
return ColorUtilsFromCompat.compositeColors(foreground, background);
}
+ public static boolean isColorLight(int backgroundColor) {
+ return calculateLuminance(backgroundColor) > 0.5f;
+ }
+
/**
* Framework copy of functions needed from android.support.v4.graphics.ColorUtils.
*/
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 2042bf62..0ee71bd 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -22,7 +22,6 @@
import "frameworks/base/libs/incident/proto/android/privacy.proto";
import "frameworks/base/core/proto/android/service/appwidget.proto";
import "frameworks/base/core/proto/android/service/battery.proto";
-import "frameworks/base/core/proto/android/service/graphicsstats.proto";
import "frameworks/base/core/proto/android/service/fingerprint.proto";
import "frameworks/base/core/proto/android/service/diskstats.proto";
import "frameworks/base/core/proto/android/service/netstats.proto";
@@ -66,5 +65,4 @@
android.service.notification.NotificationServiceDumpProto notification = 3004;
android.service.pm.PackageServiceDumpProto package = 3008;
android.service.power.PowerServiceDumpProto power = 3009;
- android.service.GraphicsStatsServiceDumpProto graphicsstats = 3005;
}
diff --git a/core/proto/android/service/fingerprint.proto b/core/proto/android/service/fingerprint.proto
index 79dba86..f88b762 100644
--- a/core/proto/android/service/fingerprint.proto
+++ b/core/proto/android/service/fingerprint.proto
@@ -54,4 +54,7 @@
// Total number of lockouts.
int32 lockout = 4;
+
+ // Total number of permanent lockouts.
+ int32 lockout_permanent = 5;
}
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index 6dbfe48..b8679b0 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -20,6 +20,7 @@
option java_multiple_files = true;
option java_outer_classname = "GraphicsStatsServiceProto";
+option optimize_for = LITE_RUNTIME;
message GraphicsStatsServiceDumpProto {
repeated GraphicsStatsProto stats = 1;
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 21ab4c3..76310b8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1335,6 +1335,8 @@
<string name="fingerprint_error_canceled">Fingerprint operation canceled.</string>
<!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. -->
<string name="fingerprint_error_lockout">Too many attempts. Try again later.</string>
+ <!-- Generic error message shown when the fingerprint operation fails because strong authentication is required -->
+ <string name="fingerprint_error_lockout_permanent">Too many attempts. Fingerprint sensor disabled.</string>
<!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
<string name="fingerprint_error_unable_to_process">Try again.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 16e933a..18c18a8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2289,6 +2289,7 @@
<java-symbol type="array" name="fingerprint_acquired_vendor" />
<java-symbol type="string" name="fingerprint_error_canceled" />
<java-symbol type="string" name="fingerprint_error_lockout" />
+ <java-symbol type="string" name="fingerprint_error_lockout_permanent" />
<java-symbol type="string" name="fingerprint_name_template" />
<!-- Fingerprint config -->
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
new file mode 100644
index 0000000..ac1ac19
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.media.session.MediaSession;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.NotificationColorUtil;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NotificationTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ @Test
+ public void testColorSatisfiedWhenBgDarkTextDarker() {
+ Notification.Builder builder = getMediaNotification();
+ builder.build();
+
+ // An initial guess where the foreground color is actually darker than an already dark bg
+ int backgroundColor = 0xff585868;
+ int initialForegroundColor = 0xff505868;
+ builder.setColorPalette(backgroundColor, initialForegroundColor);
+ int primaryTextColor = builder.getPrimaryTextColor();
+ assertTrue(satisfiesTextContrast(primaryTextColor, backgroundColor));
+ int secondaryTextColor = builder.getSecondaryTextColor();
+ assertTrue(satisfiesTextContrast(secondaryTextColor, backgroundColor));
+ }
+
+ private Notification.Builder getMediaNotification() {
+ MediaSession session = new MediaSession(mContext, "test");
+ return new Notification.Builder(mContext, "color")
+ .setSmallIcon(com.android.internal.R.drawable.emergency_icon)
+ .setContentTitle("Title")
+ .setContentText("Text")
+ .setStyle(new Notification.MediaStyle().setMediaSession(session.getSessionToken()));
+ }
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index 7b7031b..29447ed 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -124,19 +124,40 @@
int startIndex = text.indexOf(classifiedText);
int endIndex = startIndex + classifiedText.length();
assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
- isTextClassification(classifiedText, TextClassifier.TYPE_EMAIL));
+ isTextClassification(
+ classifiedText,
+ TextClassifier.TYPE_EMAIL,
+ "mailto:" + classifiedText));
}
@Test
public void testTextClassifyText_url() {
if (isTextClassifierDisabled()) return;
- String text = "Visit http://www.android.com for more information";
+ String text = "Visit www.android.com for more information";
String classifiedText = "www.android.com";
int startIndex = text.indexOf(classifiedText);
int endIndex = startIndex + classifiedText.length();
assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
- isTextClassification(classifiedText, TextClassifier.TYPE_URL));
+ isTextClassification(
+ classifiedText,
+ TextClassifier.TYPE_URL,
+ "http://" + classifiedText));
+ }
+
+ @Test
+ public void testTextClassifyText_url_inCaps() {
+ if (isTextClassifierDisabled()) return;
+
+ String text = "Visit HTTP://ANDROID.COM for more information";
+ String classifiedText = "HTTP://ANDROID.COM";
+ int startIndex = text.indexOf(classifiedText);
+ int endIndex = startIndex + classifiedText.length();
+ assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
+ isTextClassification(
+ classifiedText,
+ TextClassifier.TYPE_URL,
+ "http://ANDROID.COM"));
}
@Test
@@ -149,7 +170,10 @@
int endIndex = startIndex + classifiedText.length();
LocaleList nullLocales = null;
assertThat(mClassifier.classifyText(text, startIndex, endIndex, nullLocales),
- isTextClassification(classifiedText, TextClassifier.TYPE_EMAIL));
+ isTextClassification(
+ classifiedText,
+ TextClassifier.TYPE_EMAIL,
+ "mailto:" + classifiedText));
}
@Test
@@ -206,18 +230,23 @@
}
private static Matcher<TextClassification> isTextClassification(
- final String text, final String type) {
+ final String text, final String type, final String intentUri) {
return new BaseMatcher<TextClassification>() {
@Override
public boolean matches(Object o) {
if (o instanceof TextClassification) {
TextClassification result = (TextClassification) o;
final boolean typeRequirementSatisfied;
+ String scheme;
switch (type) {
+ case TextClassifier.TYPE_EMAIL:
+ scheme = result.getIntent().getData().getScheme();
+ typeRequirementSatisfied = "mailto".equals(scheme);
+ break;
case TextClassifier.TYPE_URL:
- String scheme = result.getIntent().getData().getScheme();
- typeRequirementSatisfied = "http".equalsIgnoreCase(scheme)
- || "https".equalsIgnoreCase(scheme);
+ scheme = result.getIntent().getData().getScheme();
+ typeRequirementSatisfied = "http".equals(scheme)
+ || "https".equals(scheme);
break;
default:
typeRequirementSatisfied = true;
@@ -226,7 +255,8 @@
return typeRequirementSatisfied
&& text.equals(result.getText())
&& result.getEntityCount() > 0
- && type.equals(result.getEntity(0));
+ && type.equals(result.getEntity(0))
+ && intentUri.equals(result.getIntent().getDataString());
// TODO: Include other properties.
}
return false;
@@ -235,7 +265,8 @@
@Override
public void describeTo(Description description) {
description.appendText("text=").appendValue(text)
- .appendText(", type=").appendValue(type);
+ .appendText(", type=").appendValue(type)
+ .appendText(", intent.data=").appendValue(intentUri);
}
};
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 1dced75..e374e11 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -29,15 +29,15 @@
private static final int UID = 10500;
private static final WorkSource WS = new WorkSource(UID);
- /** Test that BatteryStatsImpl.Uid.noteBluetoothScanResultLocked. */
+ /** Test that BatteryStatsImpl.Uid.noteBluetoothScanResultsLocked. */
@SmallTest
public void testNoteBluetoothScanResultLocked() throws Exception {
MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClocks());
bi.updateTimeBasesLocked(true, true, 0, 0);
- bi.noteBluetoothScanResultFromSourceLocked(WS);
- bi.noteBluetoothScanResultFromSourceLocked(WS);
- assertEquals(2,
+ bi.noteBluetoothScanResultsFromSourceLocked(WS, 1);
+ bi.noteBluetoothScanResultsFromSourceLocked(WS, 100);
+ assertEquals(101,
bi.getUidStats().get(UID).getBluetoothScanResultCounter()
.getCountLocked(STATS_SINCE_CHARGED));
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index acf8883..07ff27d 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -62,7 +62,7 @@
"libskia",
"libui",
"libgui",
- "libprotobuf-cpp-full",
+ "libprotobuf-cpp-lite",
"libharfbuzz_ng",
"libft2",
"libminikin",
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index ab6420e..87eaa6a 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -19,7 +19,7 @@
#include "JankTracker.h"
#include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <log/log.h>
#include <inttypes.h>
@@ -27,6 +27,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <sys/mman.h>
namespace android {
namespace uirenderer {
@@ -46,10 +47,74 @@
const ProfileData* data);
static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
+class FileDescriptor {
+public:
+ FileDescriptor(int fd) : mFd(fd) {}
+ ~FileDescriptor() {
+ if (mFd != -1) {
+ close(mFd);
+ mFd = -1;
+ }
+ }
+ bool valid() { return mFd != -1; }
+ operator int() { return mFd; }
+private:
+ int mFd;
+};
+
+class FileOutputStreamLite : public io::ZeroCopyOutputStream {
+public:
+ FileOutputStreamLite(int fd) : mCopyAdapter(fd), mImpl(&mCopyAdapter) {}
+ virtual ~FileOutputStreamLite() {}
+
+ int GetErrno() { return mCopyAdapter.mErrno; }
+
+ virtual bool Next(void** data, int* size) override {
+ return mImpl.Next(data, size);
+ }
+
+ virtual void BackUp(int count) override {
+ mImpl.BackUp(count);
+ }
+
+ virtual int64 ByteCount() const override {
+ return mImpl.ByteCount();
+ }
+
+ bool Flush() {
+ return mImpl.Flush();
+ }
+
+private:
+ struct FDAdapter : public io::CopyingOutputStream {
+ int mFd;
+ int mErrno = 0;
+
+ FDAdapter(int fd) : mFd(fd) {}
+ virtual ~FDAdapter() {}
+
+ virtual bool Write(const void* buffer, int size) override {
+ int ret;
+ while (size) {
+ ret = TEMP_FAILURE_RETRY( write(mFd, buffer, size) );
+ if (ret <= 0) {
+ mErrno = errno;
+ return false;
+ }
+ size -= ret;
+ }
+ return true;
+ }
+ };
+
+ FileOutputStreamLite::FDAdapter mCopyAdapter;
+ io::CopyingOutputStreamAdaptor mImpl;
+};
+
bool GraphicsStatsService::parseFromFile(const std::string& path, service::GraphicsStatsProto* output) {
- int fd = open(path.c_str(), O_RDONLY);
- if (fd == -1) {
+ FileDescriptor fd{open(path.c_str(), O_RDONLY)};
+ if (!fd.valid()) {
int err = errno;
// The file not existing is normal for addToDump(), so only log if
// we get an unexpected error
@@ -58,26 +123,41 @@
}
return false;
}
- uint32_t file_version;
- ssize_t bytesRead = read(fd, &file_version, sHeaderSize);
- if (bytesRead != sHeaderSize || file_version != sCurrentFileVersion) {
- ALOGW("Failed to read '%s', bytesRead=%zd file_version=%d", path.c_str(), bytesRead,
- file_version);
- close(fd);
+ struct stat sb;
+ if (fstat(fd, &sb) || sb.st_size < sHeaderSize) {
+ int err = errno;
+ // The file not existing is normal for addToDump(), so only log if
+ // we get an unexpected error
+ if (err != ENOENT) {
+ ALOGW("Failed to fstat '%s', errno=%d (%s) (st_size %d)", path.c_str(), err,
+ strerror(err), (int) sb.st_size);
+ }
+ return false;
+ }
+ void* addr = mmap(nullptr, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!addr) {
+ int err = errno;
+ // The file not existing is normal for addToDump(), so only log if
+ // we get an unexpected error
+ if (err != ENOENT) {
+ ALOGW("Failed to mmap '%s', errno=%d (%s)", path.c_str(), err, strerror(err));
+ }
+ return false;
+ }
+ uint32_t file_version = *reinterpret_cast<uint32_t*>(addr);
+ if (file_version != sCurrentFileVersion) {
+ ALOGW("file_version mismatch! expected %d got %d", sCurrentFileVersion, file_version);
return false;
}
- io::FileInputStream input(fd);
+ void* data = reinterpret_cast<uint8_t*>(addr) + sHeaderSize;
+ int dataSize = sb.st_size - sHeaderSize;
+ io::ArrayInputStream input{data, dataSize};
bool success = output->ParseFromZeroCopyStream(&input);
- if (input.GetErrno() != 0) {
- ALOGW("Error reading from fd=%d, path='%s' err=%d (%s)",
- fd, path.c_str(), input.GetErrno(), strerror(input.GetErrno()));
- success = false;
- } else if (!success) {
+ if (!success) {
ALOGW("Parse failed on '%s' error='%s'",
path.c_str(), output->InitializationErrorString().c_str());
}
- close(fd);
return success;
}
@@ -212,7 +292,7 @@
return;
}
{
- io::FileOutputStream output(outFd);
+ FileOutputStreamLite output(outFd);
bool success = statsProto.SerializeToZeroCopyStream(&output) && output.Flush();
if (output.GetErrno() != 0) {
ALOGW("Error writing to fd=%d, path='%s' err=%d (%s)",
@@ -277,7 +357,7 @@
void GraphicsStatsService::finishDump(Dump* dump) {
if (dump->type() == DumpType::Protobuf) {
- io::FileOutputStream stream(dump->fd());
+ FileOutputStreamLite stream(dump->fd());
dump->proto().SerializeToZeroCopyStream(&stream);
}
delete dump;
diff --git a/libs/hwui/tests/unit/FontRendererTests.cpp b/libs/hwui/tests/unit/FontRendererTests.cpp
index 773a7ea..ee20236 100644
--- a/libs/hwui/tests/unit/FontRendererTests.cpp
+++ b/libs/hwui/tests/unit/FontRendererTests.cpp
@@ -28,7 +28,7 @@
return true;
}
-RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, DISABLED_renderDropShadow) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, renderDropShadow) {
SkPaint paint;
paint.setTextSize(10);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
diff --git a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
index 5383e57..8312bda 100644
--- a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
+++ b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
@@ -26,7 +26,7 @@
using namespace android;
using namespace android::uirenderer;
-RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, DISABLED_addRemove) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, addRemove) {
SkPaint paint;
paint.setTextSize(20);
diff --git a/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java b/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java
index 766c42b..d9f4c44 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.settingslib;
import android.os.SystemClock;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e3ef873..d43b740 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -63,6 +63,7 @@
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
diff --git a/packages/SystemUI/res/drawable/pip_expand.xml b/packages/SystemUI/res/drawable/pip_expand.xml
new file mode 100644
index 0000000..cdb2ee5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_expand.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="36dp"
+ android:height="36dp"
+ android:viewportWidth="36"
+ android:viewportHeight="36">
+
+ <path
+ android:pathData="M0 0h36v36H0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M10 21H7v8h8v-3h-5v-5zm-3-6h3v-5h5V7H7v8zm19 11h-5v3h8v-8h-3v5zM21
+7v3h5v5h3V7h-8z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_ll.xml b/packages/SystemUI/res/drawable/pip_expand_ll.xml
deleted file mode 100644
index a8b82b5..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_ll.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="60dp"
- android:height="60dp"
- android:viewportWidth="60"
- android:viewportHeight="60">
-
- <path
- android:fillColor="#fff"
- android:pathData="M7.5,52h45a5,5,0,0,0,5-5V12.95A5,5,0,0,0,52.5,8H7.5a5,5,0,0,0-5,4.95V47A5,5,0,0,0,7.5,52Zm-1-5V13a1,1,0,0,1,1-1h45a1,1,0,0,1,1,1V47a1,1,0,0,1-1,1H7.5A1,1,0,0,1,6.5,47Z" />
- <path
- android:pathData="M0,0V60H60V0H0Z" />
- <path
- android:fillColor="#fff"
- android:pathData="M35,39.14v2a1,1,0,0,0,1,1H46.5a1,1,0,0,0,1-1V30.64a1,1,0,0,0-1-1h-2a1,1,0,0,0-1,1v7.5H36A1,1,0,0,0,35,39.14Z" />
- <path
- android:fillColor="#fff"
- android:pathData="M13.5,30.36h2a1,1,0,0,0,1-1v-7.5H24a1,1,0,0,0,1-1v-2a1,1,0,0,0-1-1H13.5a1,1,0,0,0-1,1v10.5A1,1,0,0,0,13.5,30.36Z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_lr.xml b/packages/SystemUI/res/drawable/pip_expand_lr.xml
deleted file mode 100644
index 44d97ef..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_lr.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="60dp"
- android:height="60dp"
- android:viewportWidth="60"
- android:viewportHeight="60">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M57.5,47V12.95c0-2.75-2.25-4.95-5-4.95h-45c-2.75,0-5,2.2-5,4.95V47c0,2.75,2.25,5,5,5h45
-C55.25,52,57.5,49.75,57.5,47z
-M52.5,48h-45c-0.55,0-1-0.45-1-1V13c0-0.55,0.45-1,1-1h45c0.55,0,1,0.45,1,1v34
-C53.5,47.55,53.05,48,52.5,48z" />
- <path
- android:pathData="M60,0v60H0L0,0L60,0z" />
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M25,39.14v2c0,0.55-0.45,1-1,1H13.5c-0.55,0-1-0.45-1-1v-10.5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v7.5
-H24C24.55,38.14,25,38.59,25,39.14z" />
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M46.5,30.36h-2c-0.55,0-1-0.45-1-1v-7.5H36c-0.55,0-1-0.45-1-1v-2c0-0.55,0.45-1,1-1h10.5
-c0.55,0,1,0.45,1,1v10.5C47.5,29.91,47.05,30.36,46.5,30.36z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_pl.xml b/packages/SystemUI/res/drawable/pip_expand_pl.xml
deleted file mode 100644
index 57b9358..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_pl.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="60dp"
- android:height="60dp"
- android:viewportWidth="60"
- android:viewportHeight="60">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M47,2.5H12.95C10.2,2.5,8,4.75,8,7.5v45c0,2.75,2.2,5,4.95,5H47c2.75,0,5-2.25,5-5v-45
-C52,4.75,49.75,2.5,47,2.5z
-M48,7.5v45c0,0.55-0.45,1-1,1H13c-0.55,0-1-0.45-1-1v-45c0-0.55,0.45-1,1-1h34
-C47.55,6.5,48,6.95,48,7.5z" />
- <path
- android:pathData="M0,0l60,0v60H0L0,0z" />
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M39.14,35h2c0.55,0,1,0.45,1,1v10.5c0,0.55-0.45,1-1,1h-10.5c-0.55,0-1-0.45-1-1v-2c0-0.55,0.45-1,1-1h7.5
-V36C38.14,35.45,38.59,35,39.14,35z" />
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M30.36,13.5v2c0,0.55-0.45,1-1,1h-7.5V24c0,0.55-0.45,1-1,1h-2c-0.55,0-1-0.45-1-1V13.5c0-0.55,0.45-1,1-1
-h10.5C29.91,12.5,30.36,12.95,30.36,13.5z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_pr.xml b/packages/SystemUI/res/drawable/pip_expand_pr.xml
deleted file mode 100644
index e34a95d..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_pr.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="60dp"
- android:height="60dp"
- android:viewportWidth="60"
- android:viewportHeight="60">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M8,7.5v45c0,2.75,2.25,5,5,5h34.05c2.75,0,4.95-2.25,4.95-5v-45c0-2.75-2.2-5-4.95-5H13
-C10.25,2.5,8,4.75,8,7.5z
-M13,6.5h34c0.55,0,1,0.45,1,1v45c0,0.55-0.45,1-1,1H13c-0.55,0-1-0.45-1-1v-45C12,6.95,12.45,6.5,13,6.5z" />
- <path
- android:pathData="M60,0L0,0l0,60h60V0z" />
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M20.86,35h-2c-0.55,0-1,0.45-1,1v10.5c0,0.55,0.45,1,1,1h10.5c0.55,0,1-0.45,1-1v-2c0-0.55-0.45-1-1-1h-7.5
-V36C21.86,35.45,21.41,35,20.86,35z" />
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M29.64,13.5v2c0,0.55,0.45,1,1,1h7.5V24c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1V13.5c0-0.55-0.45-1-1-1
-h-10.5C30.09,12.5,29.64,12.95,29.64,13.5z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index 8c66bab..8b7f692 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -38,6 +38,8 @@
android:layout_height="60dp"
android:layout_gravity="center"
android:contentDescription="@string/pip_phone_expand"
+ android:padding="10dp"
+ android:src="@drawable/pip_expand"
android:background="?android:selectableItemBackgroundBorderless" />
</FrameLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 97e180c..99c6227 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -792,7 +792,7 @@
<!-- The bottom margin of the expand container when there are actions.
Equal to pip_action_size - pip_action_padding. -->
- <dimen name="pip_expand_container_edge_margin">36dp</dimen>
+ <dimen name="pip_expand_container_edge_margin">30dp</dimen>
<dimen name="default_gear_space">18dp</dimen>
<dimen name="cell_overlay_padding">18dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 47290ec..dce4b61 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -512,6 +512,12 @@
}
}
+ if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+ mLockPatternUtils.requireStrongAuth(
+ LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
+ getCurrentUser());
+ }
+
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 65f24cf..766914c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -303,7 +303,6 @@
mMenuContainerAnimator.cancel();
}
notifyMenuStateChange(menuState);
- updateExpandButtonFromBounds(stackBounds, movementBounds);
mMenuContainerAnimator = new AnimatorSet();
ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
mMenuContainer.getAlpha(), 1f);
@@ -388,24 +387,6 @@
}
}
- private void updateExpandButtonFromBounds(Rect stackBounds, Rect movementBounds) {
- if (stackBounds == null) {
- return;
- }
-
- boolean isLandscapePip = stackBounds.width() > stackBounds.height();
- boolean left = stackBounds.left < movementBounds.centerX();
- boolean top = stackBounds.top < movementBounds.centerY();
- boolean expandL = (left && top) || (!left && !top);
- int iconResId;
- if (isLandscapePip) {
- iconResId = expandL ? R.drawable.pip_expand_ll : R.drawable.pip_expand_lr;
- } else {
- iconResId = expandL ? R.drawable.pip_expand_pl : R.drawable.pip_expand_pr;
- }
- mExpandButton.setImageResource(iconResId);
- }
-
private void setActions(Rect stackBounds, List<RemoteAction> actions) {
mActions.clear();
mActions.addAll(actions);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index 5b54d85..30240c3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -168,8 +168,7 @@
void onConfigurationChanged(Context context) {
Resources res = context.getResources();
mDefaultTitle = res.getString(R.string.pip_notification_unknown_title);
- mDefaultIconResId = res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR
- ? R.drawable.pip_expand_ll : R.drawable.pip_expand_lr;
+ mDefaultIconResId = R.drawable.pip_expand;
if (mNotified) {
// update notification
notifyPipNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index f6bd14c..9a3de61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -28,6 +28,7 @@
import android.support.v7.graphics.Palette;
import android.util.LayoutDirection;
+import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import java.util.List;
@@ -120,7 +121,7 @@
paletteBuilder.addFilter(mBlackWhiteFilter);
palette = paletteBuilder.generate();
int foregroundColor;
- if (ColorUtils.calculateLuminance(backgroundColor) > 0.5) {
+ if (NotificationColorUtil.isColorLight(backgroundColor)) {
Palette.Swatch first = palette.getDarkVibrantSwatch();
Palette.Swatch second = palette.getVibrantSwatch();
if (first != null && second != null) {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 7a1a5f2..38db8de 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -792,6 +792,11 @@
return false;
}
+ // 4. it is an "instant" app
+ if (app.isInstantApp()) {
+ return false;
+ }
+
// Everything else checks out; the only remaining roadblock would be if the
// package were disabled
return !appIsDisabled(app, pm);
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 8ed95ee..ff5efde 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -65,6 +65,7 @@
static final boolean DEBUG_MU = DEBUG_ALL || false;
static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
+ static final boolean DEBUG_OOM_ADJ_REASON = DEBUG_ALL || false;
static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
static final boolean DEBUG_POWER = DEBUG_ALL || false;
static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8398eee..e09dd25 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -118,6 +118,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ_REASON;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
@@ -20629,6 +20630,7 @@
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
// The max adjustment doesn't allow this app to be anything
// below foreground, so it is not worth doing work for it.
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making fixed: " + app);
app.adjType = "fixed";
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
@@ -20680,12 +20682,14 @@
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making top: " + app);
} else if (app.instr != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making instrumentation: " + app);
} else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
// An app that is currently receiving a broadcast also
// counts as being in the foreground for OOM killer purposes.
@@ -20696,6 +20700,7 @@
? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making broadcast: " + app);
} else if (app.executingServices.size() > 0) {
// An app that is currently executing a service callback also
// counts as being in the foreground.
@@ -20704,6 +20709,7 @@
ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "exec-service";
procState = ActivityManager.PROCESS_STATE_SERVICE;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making exec-service: " + app);
//Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
} else {
// As far as we know the process is empty. We may change our mind later.
@@ -20715,6 +20721,7 @@
app.cached = true;
app.empty = true;
app.adjType = "cch-empty";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making empty: " + app);
}
// Examine all activities if not already foreground.
@@ -20736,10 +20743,13 @@
// App has a visible activity; only upgrade adjustment.
if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
- app.adjType = "visible";
+ app.adjType = "vis-activity";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to vis-activity: " + app);
}
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
+ app.adjType = "vis-activity";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to vis-activity: " + app);
}
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
@@ -20756,10 +20766,13 @@
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.adjType = "pausing";
+ app.adjType = "pause-activity";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to pause-activity: " + app);
}
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
+ app.adjType = "pause-activity";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to pause-activity: " + app);
}
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
@@ -20768,7 +20781,8 @@
} else if (r.state == ActivityState.STOPPING) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.adjType = "stopping";
+ app.adjType = "stop-activity";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to stop-activity: " + app);
}
// For the process state, we will at this point consider the
// process to be cached. It will be cached either as an activity
@@ -20780,6 +20794,8 @@
if (!r.finishing) {
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+ app.adjType = "stop-activity";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to stop-activity: " + app);
}
}
app.cached = false;
@@ -20789,6 +20805,7 @@
if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
app.adjType = "cch-act";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to cached activity: " + app);
}
}
}
@@ -20806,6 +20823,7 @@
app.cached = false;
app.adjType = "fg-service";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to fg service: " + app);
} else if (app.hasOverlayUi) {
// The process is display an overlay UI.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
@@ -20813,6 +20831,7 @@
app.cached = false;
app.adjType = "has-overlay-ui";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to overlay ui: " + app);
}
}
@@ -20828,6 +20847,7 @@
app.adjType = "force-imp";
app.adjSource = app.forcingToImportant;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to force imp: " + app);
}
}
@@ -20838,9 +20858,12 @@
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "heavy";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to heavy: " + app);
}
if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
+ app.adjType = "heavy";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to heavy: " + app);
}
}
@@ -20852,9 +20875,12 @@
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "home";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to home: " + app);
}
if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME;
+ app.adjType = "home";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to home: " + app);
}
}
@@ -20867,9 +20893,12 @@
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "previous";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to prev: " + app);
}
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+ app.adjType = "previous";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to prev: " + app);
}
}
@@ -20893,14 +20922,20 @@
procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
}
app.adjType = "backup";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to backup: " + app);
app.cached = false;
}
if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
procState = ActivityManager.PROCESS_STATE_BACKUP;
+ app.adjType = "backup";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to backup: " + app);
}
}
boolean mayBeTop = false;
+ String mayBeTopType = null;
+ Object mayBeTopSource = null;
+ Object mayBeTopTarget = null;
for (int is = app.services.size()-1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
@@ -20912,6 +20947,8 @@
app.hasStartedServices = true;
if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
procState = ActivityManager.PROCESS_STATE_SERVICE;
+ app.adjType = "started-services";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to started service: " + app);
}
if (app.hasShownUi && app != mHomeProcess) {
// If this process has shown some UI, let it immediately
@@ -20929,6 +20966,7 @@
if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to started service: " + app);
app.cached = false;
}
}
@@ -21010,27 +21048,35 @@
// memory.
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
- adjType = "cch-bound-ui-services";
+ if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
+ adjType = "cch-bound-ui-services";
+ }
} else {
+ int newAdj;
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
- adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
+ newAdj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
- adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
- adj = clientAdj;
+ newAdj = clientAdj;
} else {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
- adj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
+ newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
+ } else {
+ newAdj = adj;
}
}
if (!client.cached) {
app.cached = false;
}
- adjType = "service";
+ if (adj > newAdj) {
+ adj = newAdj;
+ adjType = "service";
+ }
}
}
if ((cr.flags & (Context.BIND_NOT_FOREGROUND
@@ -21057,6 +21103,9 @@
// is more important to continue considering it to be
// in the background state.
mayBeTop = true;
+ mayBeTopType = "service";
+ mayBeTopSource = cr.binding.client;
+ mayBeTopTarget = s.name;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
} else {
// Special handling for above-top states (persistent
@@ -21093,6 +21142,9 @@
}
if (procState > clientProcState) {
procState = clientProcState;
+ if (adjType == null) {
+ adjType = "service";
+ }
}
if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
&& (cr.flags&Context.BIND_SHOWING_UI) != 0) {
@@ -21105,6 +21157,9 @@
app.adjSource = cr.binding.client;
app.adjSourceProcState = clientProcState;
app.adjTarget = s.name;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to " + adjType
+ + ": " + app + ", due to " + cr.binding.client
+ + " adj=" + adj + " procState=" + procState);
}
}
if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
@@ -21130,6 +21185,8 @@
app.adjSource = a;
app.adjSourceProcState = procState;
app.adjTarget = s.name;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to service w/activity: "
+ + app);
}
}
}
@@ -21160,21 +21217,17 @@
// we are going to consider it empty.
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
}
+ String adjType = null;
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
- app.adjType = "cch-ui-provider";
+ adjType = "cch-ui-provider";
} else {
adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
- app.adjType = "provider";
+ adjType = "provider";
}
app.cached &= client.cached;
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_PROVIDER_IN_USE;
- app.adjSource = client;
- app.adjSourceProcState = clientProcState;
- app.adjTarget = cpr.name;
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
@@ -21189,6 +21242,9 @@
// in the background state.
mayBeTop = true;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+ mayBeTopType = adjType = "provider-top";
+ mayBeTopSource = client;
+ mayBeTopTarget = cpr.name;
} else {
// Special handling for above-top states (persistent
// processes). These should not bring the current process
@@ -21196,6 +21252,9 @@
// give them the best state after that.
clientProcState =
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ if (adjType == null) {
+ adjType = "provider";
+ }
}
}
if (procState > clientProcState) {
@@ -21204,6 +21263,17 @@
if (client.curSchedGroup > schedGroup) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
+ if (adjType != null) {
+ app.adjType = adjType;
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_PROVIDER_IN_USE;
+ app.adjSource = client;
+ app.adjSourceProcState = clientProcState;
+ app.adjTarget = cpr.name;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to " + adjType
+ + ": " + app + ", due to " + client
+ + " adj=" + adj + " procState=" + procState);
+ }
}
// If the provider has external (non-framework) process
// dependencies, ensure that its adjustment is at least
@@ -21213,8 +21283,9 @@
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
- app.adjType = "provider";
+ app.adjType = "ext-provider";
app.adjTarget = cpr.name;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to external provider: " + app);
}
if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
@@ -21228,10 +21299,13 @@
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
- app.adjType = "provider";
+ app.adjType = "recent-provider";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to recent provider: " + app);
}
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+ app.adjType = "recent-provider";
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to recent provider: " + app);
}
}
@@ -21243,6 +21317,9 @@
// is top (states that tend to be longer-term) and otherwise allow it to go
// to the top state.
switch (procState) {
+ case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+ // Something else is keeping it at this level, just leave it.
+ break;
case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
@@ -21250,10 +21327,22 @@
// These all are longer-term states, so pull them up to the top
// of the background states, but not all the way to the top state.
procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ app.adjType = mayBeTopType;
+ app.adjSource = mayBeTopSource;
+ app.adjTarget = mayBeTopTarget;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "May be top raise to " + mayBeTopType
+ + ": " + app + ", due to " + mayBeTopSource
+ + " adj=" + adj + " procState=" + procState);
break;
default:
// Otherwise, top is a better choice, so take it.
procState = ActivityManager.PROCESS_STATE_TOP;
+ app.adjType = mayBeTopType;
+ app.adjSource = mayBeTopSource;
+ app.adjTarget = mayBeTopTarget;
+ if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "May be top raise to " + mayBeTopType
+ + ": " + app + ", due to " + mayBeTopSource
+ + " adj=" + adj + " procState=" + procState);
break;
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 5d8cb12..4db5c85 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -989,10 +989,10 @@
}
@Override
- public void noteBleScanResult(WorkSource ws) {
+ public void noteBleScanResults(WorkSource ws, int numNewResults) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteBluetoothScanResultFromSourceLocked(ws);
+ mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults);
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 80e7c75..7810c5e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -356,7 +356,7 @@
procState = "PERU";
break;
case ActivityManager.PROCESS_STATE_TOP:
- procState = "TOP";
+ procState = "TOP ";
break;
case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
procState = "BFGS";
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index fe49813..4fc6ddd 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -34,8 +34,13 @@
public abstract class AuthenticationClient extends ClientMonitor {
private long mOpId;
- public abstract boolean handleFailedAttempt();
+ public abstract int handleFailedAttempt();
public abstract void resetFailedAttempts();
+
+ public static final int LOCKOUT_NONE = 0;
+ public static final int LOCKOUT_TIMED = 1;
+ public static final int LOCKOUT_PERMANENT = 2;
+
private boolean mAlreadyCancelled;
public AuthenticationClient(Context context, long halDeviceId, IBinder token,
@@ -79,19 +84,21 @@
FingerprintUtils.vibrateFingerprintError(getContext());
}
// allow system-defined limit of number of attempts before giving up
- boolean inLockoutMode = handleFailedAttempt();
- // send lockout event in case driver doesn't enforce it.
- if (inLockoutMode) {
+ int lockoutMode = handleFailedAttempt();
+ if (lockoutMode != LOCKOUT_NONE) {
try {
- Slog.w(TAG, "Forcing lockout (fp driver code should do this!)");
- stop(false); // cancel fingerprint authentication
- receiver.onError(getHalDeviceId(),
- FingerprintManager.FINGERPRINT_ERROR_LOCKOUT, 0 /* vendorCode */);
+ Slog.w(TAG, "Forcing lockout (fp driver code should do this!), mode(" +
+ lockoutMode + ")");
+ stop(false);
+ int errorCode = lockoutMode == LOCKOUT_TIMED ?
+ FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
+ FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+ receiver.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to notify lockout:", e);
}
}
- result |= inLockoutMode;
+ result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode
} else {
if (receiver != null) {
FingerprintUtils.vibrateFingerprintSuccess(getContext());
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 6f5b028..6cc7071 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -108,6 +108,7 @@
int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image
// acquisition in some cases (too fast, too slow, dirty sensor, etc.)
int lockout; // total number of lockouts
+ int permanentLockout; // total number of permanent lockouts
}
private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
@@ -118,13 +119,16 @@
Collections.synchronizedMap(new HashMap<>());
private final AppOpsManager mAppOps;
private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
- private static final int MAX_FAILED_ATTEMPTS = 5;
+ private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5;
+ private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20;
+
private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
private final String mKeyguardPackage;
private int mCurrentUserId = UserHandle.USER_NULL;
private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();
private Context mContext;
private long mHalDeviceId;
+ private boolean mTimedLockoutCleared;
private int mFailedAttempts;
@GuardedBy("this")
private IBiometricsFingerprint mDaemon;
@@ -173,7 +177,7 @@
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) {
- resetFailedAttempts();
+ resetFailedAttempts(false /* clearAttemptCounter */);
}
}
};
@@ -181,7 +185,7 @@
private final Runnable mResetFailedAttemptsRunnable = new Runnable() {
@Override
public void run() {
- resetFailedAttempts();
+ resetFailedAttempts(true /* clearAttemptCounter */);
}
};
@@ -369,6 +373,7 @@
if (client != null && client.onError(error, vendorCode)) {
removeClient(client);
}
+
if (DEBUG) Slog.v(TAG, "handleError(client="
+ (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")");
// This is the magic code that starts the next client when the old client finishes.
@@ -438,7 +443,7 @@
if (client != null && client.onAcquired(acquiredInfo, vendorCode)) {
removeClient(client);
}
- if (mPerformanceStats != null && !inLockoutMode()
+ if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE
&& client instanceof AuthenticationClient) {
// ignore enrollment acquisitions or acquisitions when we're locked out
mPerformanceStats.acquire++;
@@ -482,8 +487,14 @@
}
}
- private boolean inLockoutMode() {
- return mFailedAttempts >= MAX_FAILED_ATTEMPTS;
+ private int getLockoutMode() {
+ if (mFailedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) {
+ return AuthenticationClient.LOCKOUT_PERMANENT;
+ } else if (mFailedAttempts > 0 && mTimedLockoutCleared == false &&
+ (mFailedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) {
+ return AuthenticationClient.LOCKOUT_TIMED;
+ }
+ return AuthenticationClient.LOCKOUT_NONE;
}
private void scheduleLockoutReset() {
@@ -801,22 +812,27 @@
AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) {
@Override
- public boolean handleFailedAttempt() {
+ public int handleFailedAttempt() {
mFailedAttempts++;
- if (mFailedAttempts == MAX_FAILED_ATTEMPTS) {
+ mTimedLockoutCleared = false;
+ final int lockoutMode = getLockoutMode();
+ if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
+ mPerformanceStats.permanentLockout++;
+ } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
mPerformanceStats.lockout++;
}
- if (inLockoutMode()) {
- // Failing multiple times will continue to push out the lockout time.
+
+ // Failing multiple times will continue to push out the lockout time
+ if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
scheduleLockoutReset();
- return true;
+ return lockoutMode;
}
- return false;
+ return AuthenticationClient.LOCKOUT_NONE;
}
@Override
public void resetFailedAttempts() {
- FingerprintService.this.resetFailedAttempts();
+ FingerprintService.this.resetFailedAttempts(true /* clearAttemptCounter */);
}
@Override
@@ -830,11 +846,15 @@
}
};
- if (inLockoutMode()) {
- Slog.v(TAG, "In lockout mode; disallowing authentication");
- // Don't bother starting the client. Just send the error message.
- if (!client.onError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT, 0 /* vendorCode */)) {
- Slog.w(TAG, "Cannot send timeout message to client");
+ int lockoutMode = getLockoutMode();
+ if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
+ Slog.v(TAG, "In lockout mode(" + lockoutMode +
+ ") ; disallowing authentication");
+ int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
+ FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
+ FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+ if (!client.onError(errorCode, 0 /* vendorCode */)) {
+ Slog.w(TAG, "Cannot send permanent lockout message to client");
}
return;
}
@@ -864,11 +884,16 @@
startClient(client, true /* initiatedByClient */);
}
- protected void resetFailedAttempts() {
- if (DEBUG && inLockoutMode()) {
- Slog.v(TAG, "Reset fingerprint lockout");
+ // attempt counter should only be cleared when Keyguard goes away or when
+ // a fingerprint is successfully authenticated
+ protected void resetFailedAttempts(boolean clearAttemptCounter) {
+ if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) {
+ Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter);
}
- mFailedAttempts = 0;
+ if (clearAttemptCounter) {
+ mFailedAttempts = 0;
+ }
+ mTimedLockoutCleared = true;
// If we're asked to reset failed attempts externally (i.e. from Keyguard),
// the alarm might still be pending; remove it.
cancelLockoutReset();
@@ -1301,6 +1326,7 @@
set.put("reject", (stats != null) ? stats.reject : 0);
set.put("acquire", (stats != null) ? stats.acquire : 0);
set.put("lockout", (stats != null) ? stats.lockout : 0);
+ set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0);
// cryptoStats measures statistics about secure fingerprint transactions
// (e.g. to unlock password storage, make secure purchases, etc.)
set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0);
@@ -1336,6 +1362,7 @@
proto.write(FingerprintActionStatsProto.REJECT, normal.reject);
proto.write(FingerprintActionStatsProto.ACQUIRE, normal.acquire);
proto.write(FingerprintActionStatsProto.LOCKOUT, normal.lockout);
+ proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, normal.lockout);
proto.end(countsToken);
}
@@ -1348,6 +1375,7 @@
proto.write(FingerprintActionStatsProto.REJECT, crypto.reject);
proto.write(FingerprintActionStatsProto.ACQUIRE, crypto.acquire);
proto.write(FingerprintActionStatsProto.LOCKOUT, crypto.lockout);
+ proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, crypto.lockout);
proto.end(countsToken);
}
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 2e6cd3f..57b1ccc 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -807,7 +807,7 @@
ArrayList<JobStatus> result = new ArrayList<JobStatus>();
for (int i = mJobs.size() - 1; i >= 0; i--) {
if (UserHandle.getUserId(mJobs.keyAt(i)) == userId) {
- ArraySet<JobStatus> jobs = mJobs.get(i);
+ ArraySet<JobStatus> jobs = mJobs.valueAt(i);
if (jobs != null) {
result.addAll(jobs);
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 0e1f485..ef3e7bc 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -20,6 +20,7 @@
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_CHANGED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
+import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.pm.PackageManager.SIGNATURE_MATCH;
@@ -46,6 +47,7 @@
import android.os.ShellCallback;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -243,11 +245,14 @@
packageFilter, null, null);
final IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(ACTION_USER_ADDED);
userFilter.addAction(ACTION_USER_REMOVED);
getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
userFilter, null, null);
restoreSettings();
+
+ initIfNeeded();
onSwitchUser(UserHandle.USER_SYSTEM);
publishBinderService(Context.OVERLAY_SERVICE, mService);
@@ -269,14 +274,31 @@
}
}
+ private void initIfNeeded() {
+ final UserManager um = getContext().getSystemService(UserManager.class);
+ final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
+ synchronized (mLock) {
+ final int userCount = users.size();
+ for (int i = 0; i < userCount; i++) {
+ final UserInfo userInfo = users.get(i);
+ if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) {
+ // Initialize any users that can't be switched to, as there state would
+ // never be setup in onSwitchUser(). We will switch to the system user right
+ // after this, and its state will be setup there.
+ final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id);
+ updateOverlayPaths(users.get(i).id, targets);
+ }
+ }
+ }
+ }
+
@Override
public void onSwitchUser(final int newUserId) {
// ensure overlays in the settings are up-to-date, and propagate
// any asset changes to the rest of the system
- final List<String> targets;
synchronized (mLock) {
- targets = mImpl.onSwitchUser(newUserId);
- updateAssetsLocked(newUserId, targets);
+ final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
+ updateAssets(newUserId, targets);
}
schedulePersistSettings();
}
@@ -428,10 +450,19 @@
private final class UserReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
switch (intent.getAction()) {
+ case ACTION_USER_ADDED:
+ if (userId != UserHandle.USER_NULL) {
+ final ArrayList<String> targets;
+ synchronized (mLock) {
+ targets = mImpl.updateOverlaysForUser(userId);
+ }
+ updateOverlayPaths(userId, targets);
+ }
+ break;
+
case ACTION_USER_REMOVED:
- final int userId =
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
if (userId != UserHandle.USER_NULL) {
synchronized (mLock) {
mImpl.onUserRemoved(userId);
@@ -647,9 +678,7 @@
public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
schedulePersistSettings();
FgThread.getHandler().post(() -> {
- synchronized (mLock) {
- updateAssetsLocked(userId, targetPackageName);
- }
+ updateAssets(userId, targetPackageName);
final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED,
Uri.fromParts("package", targetPackageName, null));
@@ -670,13 +699,10 @@
}
}
- private void updateAssetsLocked(final int userId, final String targetPackageName) {
- final List<String> list = new ArrayList<>();
- list.add(targetPackageName);
- updateAssetsLocked(userId, list);
- }
-
- private void updateAssetsLocked(final int userId, List<String> targetPackageNames) {
+ /**
+ * Updates the target packages' set of enabled overlays in PackageManager.
+ */
+ private void updateOverlayPaths(int userId, List<String> targetPackageNames) {
if (DEBUG) {
Slog.d(TAG, "Updating overlay assets");
}
@@ -706,12 +732,19 @@
}
if (!pm.setEnabledOverlayPackages(
- userId, targetPackageName, pendingChanges.get(targetPackageName))) {
+ userId, targetPackageName, pendingChanges.get(targetPackageName))) {
Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
- targetPackageName, userId));
+ targetPackageName, userId));
}
}
+ }
+ private void updateAssets(final int userId, final String targetPackageName) {
+ updateAssets(userId, Collections.singletonList(targetPackageName));
+ }
+
+ private void updateAssets(final int userId, List<String> targetPackageNames) {
+ updateOverlayPaths(userId, targetPackageNames);
final IActivityManager am = ActivityManager.getService();
try {
am.scheduleApplicationInfoChanged(targetPackageNames, userId);
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 5196c66..261bcc5 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -68,15 +68,15 @@
mListener = listener;
}
- /*
- * Call this when switching to a new Android user. Will return a list of
- * target packages that must refresh their overlays. This list is the union
+ /**
+ * Call this to synchronize the Settings for a user with what PackageManager knows about a user.
+ * Returns a list of target packages that must refresh their overlays. This list is the union
* of two sets: the set of targets with currently active overlays, and the
* set of targets that had, but no longer have, active overlays.
*/
- List<String> onSwitchUser(final int newUserId) {
+ ArrayList<String> updateOverlaysForUser(final int newUserId) {
if (DEBUG) {
- Slog.d(TAG, "onSwitchUser newUserId=" + newUserId);
+ Slog.d(TAG, "updateOverlaysForUser newUserId=" + newUserId);
}
final Set<String> packagesToUpdateAssets = new ArraySet<>();
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 2f83793..353b710 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -22,12 +22,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.om.OverlayInfo;
+import android.os.UserHandle;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -266,32 +268,32 @@
return true;
}
- private static final String TAB1 = " ";
- private static final String TAB2 = TAB1 + TAB1;
- private static final String TAB3 = TAB2 + TAB1;
-
- void dump(@NonNull final PrintWriter pw) {
+ void dump(@NonNull final PrintWriter p) {
+ final IndentingPrintWriter pw = new IndentingPrintWriter(p, " ");
pw.println("Settings");
- pw.println(TAB1 + "Items");
+ pw.increaseIndent();
if (mItems.isEmpty()) {
- pw.println(TAB2 + "<none>");
+ pw.println("<none>");
return;
}
final int N = mItems.size();
for (int i = 0; i < N; i++) {
final SettingsItem item = mItems.get(i);
- final StringBuilder sb = new StringBuilder();
- sb.append(TAB2 + item.mPackageName + ":" + item.getUserId() + " {\n");
- sb.append(TAB3 + "mPackageName.......: " + item.mPackageName + "\n");
- sb.append(TAB3 + "mUserId............: " + item.getUserId() + "\n");
- sb.append(TAB3 + "mTargetPackageName.: " + item.getTargetPackageName() + "\n");
- sb.append(TAB3 + "mBaseCodePath......: " + item.getBaseCodePath() + "\n");
- sb.append(TAB3 + "mState.............: " + OverlayInfo.stateToString(item.getState()) + "\n");
- sb.append(TAB3 + "mIsEnabled.........: " + item.isEnabled() + "\n");
- sb.append(TAB2 + "}");
- pw.println(sb.toString());
+ pw.println(item.mPackageName + ":" + item.getUserId() + " {");
+ pw.increaseIndent();
+
+ pw.print("mPackageName.......: "); pw.println(item.mPackageName);
+ pw.print("mUserId............: "); pw.println(item.getUserId());
+ pw.print("mTargetPackageName.: "); pw.println(item.getTargetPackageName());
+ pw.print("mBaseCodePath......: "); pw.println(item.getBaseCodePath());
+ pw.print("mState.............: "); pw.println(OverlayInfo.stateToString(item.getState()));
+ pw.print("mIsEnabled.........: "); pw.println(item.isEnabled());
+ pw.print("mIsStatic..........: "); pw.println(item.isStatic());
+
+ pw.decreaseIndent();
+ pw.println("}");
}
}
@@ -527,12 +529,6 @@
.filter(item -> item.getTargetPackageName().equals(targetPackageName));
}
- private void assertNotNull(@Nullable final Object o) {
- if (o == null) {
- throw new AndroidRuntimeException("object must not be null");
- }
- }
-
static final class BadKeyException extends RuntimeException {
BadKeyException(@NonNull final String packageName, final int userId) {
super("Bad key mPackageName=" + packageName + " mUserId=" + userId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1129076..8fcfc8f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -29,7 +29,6 @@
import static com.android.server.pm.PackageInstallerService.prepareStageDir;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
@@ -46,7 +45,6 @@
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.Signature;
-import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.FileBridge;
@@ -56,7 +54,6 @@
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.ProxyFileDescriptorCallback;
import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
import android.os.UserHandle;
@@ -1168,19 +1165,7 @@
// Send broadcast to default launcher only if it's a new install
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
if (success && isNewInstall) {
- UserManagerService ums = UserManagerService.getInstance();
- if (ums != null) {
- final UserInfo parent = ums.getProfileParent(userId);
- final int launcherUid = (parent != null) ? parent.id : userId;
- final ComponentName launcherComponent = mPm.getDefaultHomeActivity(launcherUid);
- if (launcherComponent != null) {
- Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
- .putExtra(PackageInstaller.EXTRA_SESSION, generateInfo())
- .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
- .setPackage(launcherComponent.getPackageName());
- mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
- }
- }
+ mPm.sendSessionCommitBroadcast(generateInfo(), userId);
}
mCallback.onSessionFinished(this, success);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9c76f84..baea5c6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3186,6 +3186,17 @@
return null;
}
+ @Override
+ public @Nullable ComponentName getInstantAppResolverComponent() {
+ synchronized (mPackages) {
+ final Pair<ComponentName, String> instantAppResolver = getInstantAppResolverLPr();
+ if (instantAppResolver == null) {
+ return null;
+ }
+ return instantAppResolver.first;
+ }
+ }
+
private @Nullable Pair<ComponentName, String> getInstantAppResolverLPr() {
final String[] packageArray =
mContext.getResources().getStringArray(R.array.config_ephemeralResolverPackage);
@@ -13681,6 +13692,12 @@
int userId) {
final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
sendPackageAddedForNewUsers(packageName, isSystem, pkgSetting.appId, userId);
+
+ // Send a session commit broadcast
+ final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo();
+ info.installReason = pkgSetting.getInstallReason(userId);
+ info.appPackageName = packageName;
+ sendSessionCommitBroadcast(info, userId);
}
public void sendPackageAddedForNewUsers(String packageName, boolean isSystem, int appId, int... userIds) {
@@ -20197,11 +20214,27 @@
return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
}
+ public void sendSessionCommitBroadcast(PackageInstaller.SessionInfo sessionInfo, int userId) {
+ UserManagerService ums = UserManagerService.getInstance();
+ if (ums != null) {
+ final UserInfo parent = ums.getProfileParent(userId);
+ final int launcherUid = (parent != null) ? parent.id : userId;
+ final ComponentName launcherComponent = getDefaultHomeActivity(launcherUid);
+ if (launcherComponent != null) {
+ Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
+ .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
+ .setPackage(launcherComponent.getPackageName());
+ mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
+ }
+ }
+ }
+
/**
* Report the 'Home' activity which is currently set as "always use this one". If non is set
* then reports the most likely home activity or null if there are more than one.
*/
- public ComponentName getDefaultHomeActivity(int userId) {
+ private ComponentName getDefaultHomeActivity(int userId) {
List<ResolveInfo> allHomeCandidates = new ArrayList<>();
ComponentName cn = getHomeActivitiesAsUser(allHomeCandidates, userId);
if (cn != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 3e920d4..bf92ce7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -148,6 +148,8 @@
return runSetHomeActivity();
case "get-privapp-permissions":
return runGetPrivappPermissions();
+ case "get-instantapp-resolver":
+ return runGetInstantAppResolver();
case "has-feature":
return runHasFeature();
default:
@@ -1272,6 +1274,21 @@
return 0;
}
+ private int runGetInstantAppResolver() {
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
+ if (instantAppsResolver == null) {
+ return 1;
+ }
+ pw.println(instantAppsResolver.flattenToString());
+ return 0;
+ } catch (Exception e) {
+ pw.println(e.toString());
+ return 1;
+ }
+ }
+
private int runHasFeature() {
final PrintWriter err = getErrPrintWriter();
final String featureName = getNextArg();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ac4b828..feeee3f 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -54,6 +54,7 @@
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Canvas;
import android.graphics.RectF;
+import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
@@ -1356,7 +1357,7 @@
if (icon == null) {
return; // has no icon
}
-
+ int maxIconDimension = mMaxIconDimension;
Bitmap bitmap;
try {
switch (icon.getType()) {
@@ -1368,9 +1369,12 @@
return;
}
case Icon.TYPE_BITMAP:
- case Icon.TYPE_ADAPTIVE_BITMAP: {
bitmap = icon.getBitmap(); // Don't recycle in this case.
break;
+ case Icon.TYPE_ADAPTIVE_BITMAP: {
+ bitmap = icon.getBitmap(); // Don't recycle in this case.
+ maxIconDimension *= (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
+
}
default:
// This shouldn't happen because we've already validated the icon, but
@@ -1378,7 +1382,7 @@
throw ShortcutInfo.getInvalidIconException();
}
mShortcutBitmapSaver.saveBitmapLocked(shortcut,
- mMaxIconDimension, mIconPersistFormat, mIconPersistQuality);
+ maxIconDimension, mIconPersistFormat, mIconPersistQuality);
} finally {
// Once saved, we won't use the original icon information, so null it out.
shortcut.clearIcon();
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 82416ec..fc4ec28 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -158,19 +158,23 @@
/**
* Reloads all the resources for the current configuration.
*/
- void reloadResources() {
+ private void reloadResources() {
final Resources res = mService.mContext.getResources();
mMinSize = res.getDimensionPixelSize(
com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
mDefaultAspectRatio = res.getFloat(
com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
- final Size screenEdgeInsetsDp = Size.parseSize(res.getString(
- com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets));
+ final String screenEdgeInsetsDpString = res.getString(
+ com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
+ final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
+ ? Size.parseSize(screenEdgeInsetsDpString)
+ : null;
mDefaultStackGravity = res.getInteger(
com.android.internal.R.integer.config_defaultPictureInPictureGravity);
mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics);
- mScreenEdgeInsets = new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
- dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
+ mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point()
+ : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
+ dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
mMinAspectRatio = res.getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
mMaxAspectRatio = res.getFloat(
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a6b95d6..6cb4ddc 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1310,6 +1310,10 @@
}
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
+ if (mSurfaceController == null) {
+ return;
+ }
+
final WindowState w = mWin;
final LayoutParams attrs = mWin.getAttrs();
final Task task = w.getTask();
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index 2663aaf..f4c4ea9 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -16,10 +16,10 @@
package com.android.server.appwidget;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -35,10 +35,8 @@
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.IntentSender;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutServiceInternal;
-import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.test.InstrumentationTestCase;
@@ -113,19 +111,18 @@
ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
// Set up users.
when(mMockShortcutService.requestPinAppWidget(anyString(),
- any(AppWidgetProviderInfo.class), any(Bundle.class), any(IntentSender.class), anyInt()))
+ any(AppWidgetProviderInfo.class), eq(null), eq(null), anyInt()))
.thenReturn(true);
assertTrue(mManager.requestPinAppWidget(provider, null, null));
final ArgumentCaptor<AppWidgetProviderInfo> providerCaptor =
ArgumentCaptor.forClass(AppWidgetProviderInfo.class);
verify(mMockShortcutService, times(1)).requestPinAppWidget(anyString(),
- providerCaptor.capture(), any(null), eq(null), anyInt());
+ providerCaptor.capture(), eq(null), eq(null), anyInt());
assertEquals(provider, providerCaptor.getValue().provider);
}
public void testIsRequestPinAppWidgetSupported() {
- ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
// Set up users.
when(mMockShortcutService.isRequestPinItemSupported(anyInt(), anyInt()))
.thenReturn(true, false);
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
index f124df9..45b107d 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
@@ -635,6 +635,12 @@
}
@Override
+ public int installExistingPackage(String packageName, int installReason)
+ throws NameNotFoundException {
+ return 0;
+ }
+
+ @Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
return 0;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 1284b1b..0e8960e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -498,6 +498,7 @@
pkg.mRestrictedAccountType = "foo19";
pkg.mRequiredAccountType = "foo20";
pkg.mOverlayTarget = "foo21";
+ pkg.mOverlayPriority = 100;
pkg.mSigningKeys = new ArraySet<>();
pkg.mUpgradeKeySets = new ArraySet<>();
pkg.mKeySetMapping = new ArrayMap<>();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 0167654..32eee84 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -120,18 +120,21 @@
@After
public void tearDown() throws Exception {
final LinkedList<WindowState> nonCommonWindows = new LinkedList();
- sWm.mRoot.forAllWindows(w -> {
- if (!mCommonWindows.contains(w)) {
- nonCommonWindows.addLast(w);
+
+ synchronized (sWm.mWindowMap) {
+ sWm.mRoot.forAllWindows(w -> {
+ if (!mCommonWindows.contains(w)) {
+ nonCommonWindows.addLast(w);
+ }
+ }, true /* traverseTopToBottom */);
+
+ while (!nonCommonWindows.isEmpty()) {
+ nonCommonWindows.pollLast().removeImmediately();
}
- }, true /* traverseTopToBottom */);
- while (!nonCommonWindows.isEmpty()) {
- nonCommonWindows.pollLast().removeImmediately();
+ mDisplayContent.removeImmediately();
+ sWm.mInputMethodTarget = null;
}
-
- mDisplayContent.removeImmediately();
- sWm.mInputMethodTarget = null;
}
private WindowState createCommonWindow(WindowState parent, int type, String name) {
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index bd8492b3..48f07d6 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -45,6 +45,8 @@
public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106;
// No pending incoming call exists
public static final int CODE_LOCAL_NO_PENDING_CALL = 107;
+ // IMS Call ended during conference merge process
+ public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108;
// IMS -> Telephony
// Service unavailable; by power off
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 9a03c53..3cb1f39 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -987,6 +987,15 @@
* @hide
*/
@Override
+ public int installExistingPackage(String packageName, int installReason)
+ throws NameNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
throw new UnsupportedOperationException();
diff --git a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
index 1156b01..1a4067f 100644
--- a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
+++ b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
@@ -17,4 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.aapt.app.one" coreApp="true">
<uses-sdk android:minSdkVersion="21" />
+
+ <uses-permission-sdk-23 android:name="android.permission.TEST" android:maxSdkVersion="22" />
</manifest>
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index f998d31..53c66a6 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -295,6 +295,7 @@
manifest_action["original-package"];
manifest_action["protected-broadcast"];
manifest_action["uses-permission"];
+ manifest_action["uses-permission-sdk-23"];
manifest_action["permission"];
manifest_action["permission-tree"];
manifest_action["permission-group"];