Merge "DO NOT MERGE: Kill Wifi Badging in OC." into oc-dev
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 38ce427..854e531 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -473,9 +473,13 @@
if (mReversing) {
// Between start() and first frame, mLastEventId would be unset (i.e. -1)
mLastEventId = mLastEventId == -1 ? mEvents.size() : mLastEventId;
- for (int j = mLastEventId - 1; j >= 0; j--) {
- AnimationEvent event = mEvents.get(j);
+ while (mLastEventId > 0) {
+ mLastEventId = mLastEventId - 1;
+ AnimationEvent event = mEvents.get(mLastEventId);
Animator anim = event.mNode.mAnimation;
+ if (mNodeMap.get(anim).mEnded) {
+ continue;
+ }
if (event.mEvent == AnimationEvent.ANIMATION_END) {
anim.reverse();
} else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
@@ -487,9 +491,15 @@
}
}
} else {
- for (int j = mLastEventId + 1; j < mEvents.size(); j++) {
- AnimationEvent event = mEvents.get(j);
+ while (mLastEventId < mEvents.size() - 1) {
+ // Avoid potential reentrant loop caused by child animators manipulating
+ // AnimatorSet's lifecycle (i.e. not a recommended approach).
+ mLastEventId = mLastEventId + 1;
+ AnimationEvent event = mEvents.get(mLastEventId);
Animator anim = event.mNode.mAnimation;
+ if (mNodeMap.get(anim).mEnded) {
+ continue;
+ }
if (event.mEvent == AnimationEvent.ANIMATION_START) {
anim.start();
} else if (event.mEvent == AnimationEvent.ANIMATION_END && anim.isStarted()) {
@@ -663,6 +673,10 @@
* <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which
* it is responsible. The details of when exactly those animations are started depends on
* the dependency relationships that have been set up between the animations.
+ *
+ * <b>Note:</b> Manipulating AnimatorSet's lifecycle in the child animators' listener callbacks
+ * will lead to undefined behaviors. Also, AnimatorSet will ignore any seeking in the child
+ * animators once {@link #start()} is called.
*/
@SuppressWarnings("unchecked")
@Override
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ad6b454..4dd71b4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1171,7 +1171,7 @@
*/
public static final int GROUP_ALERT_CHILDREN = 2;
- private int mGroupAlertBehavior = GROUP_ALERT_CHILDREN;
+ private int mGroupAlertBehavior = GROUP_ALERT_ALL;
/**
* If this notification is being shown as a badge, always show as a number.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 9b0bab4..5e5a6fc 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -7000,6 +7000,7 @@
return null;
}
if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
+ updateApplicationInfo(a.info.applicationInfo, flags, state);
return a.info;
}
// Make shallow copies so we can store the metadata safely
@@ -7088,6 +7089,7 @@
return null;
}
if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
+ updateApplicationInfo(s.info.applicationInfo, flags, state);
return s.info;
}
// Make shallow copies so we can store the metadata safely
@@ -7183,6 +7185,7 @@
if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
&& ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
|| p.info.uriPermissionPatterns == null)) {
+ updateApplicationInfo(p.info.applicationInfo, flags, state);
return p.info;
}
// Make shallow copies so we can store the metadata safely
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index a6cdb03..5046735 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1403,23 +1403,7 @@
/** {@hide} */
public static File maybeTranslateEmulatedPathToInternal(File path) {
- final IStorageManager storageManager = IStorageManager.Stub.asInterface(
- ServiceManager.getService("mount"));
- try {
- final VolumeInfo[] vols = storageManager.getVolumes(0);
- for (VolumeInfo vol : vols) {
- if ((vol.getType() == VolumeInfo.TYPE_EMULATED
- || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
- final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
- vol.getInternalPath(), path);
- if (internalPath != null && internalPath.exists()) {
- return internalPath;
- }
- }
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ // Disabled now that FUSE has been replaced by sdcardfs
return path;
}
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
index 251d346..6956c8a 100644
--- a/core/java/android/service/autofill/FillContext.java
+++ b/core/java/android/service/autofill/FillContext.java
@@ -114,7 +114,7 @@
*
* @hide
*/
- @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId[] ids) {
+ @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId... ids) {
final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
final ViewNode[] foundNodes = new AssistStructure.ViewNode[ids.length];
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index a97babd..ef78559 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -454,7 +454,7 @@
}
private void updateOpaqueFlag() {
- if (PixelFormat.formatHasAlpha(mRequestedFormat)) {
+ if (!PixelFormat.formatHasAlpha(mRequestedFormat)) {
mSurfaceFlags |= SurfaceControl.OPAQUE;
} else {
mSurfaceFlags &= ~SurfaceControl.OPAQUE;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 8637593..4b79b8c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4936,9 +4936,6 @@
needGlobalAttributesUpdate(true);
}
ai.mKeepScreenOn = lastKeepOn;
- if (!childHasFocus && child.hasFocusable()) {
- focusableViewAvailable(child);
- }
}
if (child.isLayoutDirectionInherited()) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 1fef7cb..c19ee56 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3842,11 +3842,12 @@
}
if (mTextView.canRequestAutofill()) {
- final int mode = mTextView.getText().length() <= 0
- ? MenuItem.SHOW_AS_ACTION_IF_ROOM : MenuItem.SHOW_AS_ACTION_NEVER;
- menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
- com.android.internal.R.string.autofill)
- .setShowAsAction(mode);
+ final String selected = mTextView.getSelectedText();
+ if (selected == null || selected.isEmpty()) {
+ menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+ com.android.internal.R.string.autofill)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ }
}
if (mTextView.canPasteAsPlainText()) {
diff --git a/core/res/res/drawable/sym_def_app_icon.xml b/core/res/res/drawable/sym_def_app_icon.xml
index 9c02402..129d38a 100644
--- a/core/res/res/drawable/sym_def_app_icon.xml
+++ b/core/res/res/drawable/sym_def_app_icon.xml
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="@android:color/white" />
+ <background android:drawable="@drawable/sym_def_app_icon_background" />
<foreground>
- <inset android:inset="27.7%">
- <bitmap android:src="@mipmap/sym_def_app_icon"/>
- </inset>
+ <bitmap android:src="@mipmap/sym_def_app_icon_foreground"/>
</foreground>
</adaptive-icon>
diff --git a/core/res/res/drawable/sym_def_app_icon_background.xml b/core/res/res/drawable/sym_def_app_icon_background.xml
new file mode 100644
index 0000000..5755210
--- /dev/null
+++ b/core/res/res/drawable/sym_def_app_icon_background.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+ android:height="108dp"
+ android:width="108dp"
+ android:viewportHeight="108.0"
+ android:viewportWidth="108.0"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/material_deep_teal_500"
+ android:pathData="M0,0h108v108h-108z"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
+ android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+</vector>
+
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..4e526c9
--- /dev/null
+++ b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index bf58413..0000000
--- a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..2c38c71
--- /dev/null
+++ b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 47f6f81..0000000
--- a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..072467e
--- /dev/null
+++ b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index f60b896..0000000
--- a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..78a6b7a
--- /dev/null
+++ b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 6d4f315..0000000
--- a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..68ebe33
--- /dev/null
+++ b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 08e54d0..0000000
--- a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ec0b049..241e565 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2536,6 +2536,10 @@
<!-- The default vibration strength, must be between 1 and 255 inclusive. -->
<integer name="config_defaultVibrationAmplitude">255</integer>
+ <!-- If the device should still vibrate even in low power mode, for certain priority vibrations
+ (e.g. accessibility, alarms). This is mainly for Wear devices that don't have speakers. -->
+ <bool name="config_allowPriorityVibrationsInLowPowerMode">false</bool>
+
<!-- Number of retries Cell Data should attempt for a given error code before
restarting the modem.
Error codes not listed will not lead to modem restarts.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 90ece60..3eebe7e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -191,21 +191,15 @@
<!-- Notification title to tell the user that data service is blocked by access control. -->
<string name="RestrictedOnDataTitle">No data service</string>
- <!-- Notification title to tell the user that emergency service is blocked by access control. -->
- <string name="RestrictedOnEmergencyTitle">No emergency service</string>
+ <!-- Notification title to tell the user that emergency calling is blocked by access control. -->
+ <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
<!-- Notification title to tell the user that normal service is blocked by access control. -->
<string name="RestrictedOnNormalTitle">No voice service</string>
<!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
<string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
- <!-- Notification content to tell the user that data service is blocked by access control. -->
- <string name="RestrictedOnDataContent">Your carrier has temporarily suspended data service at this location</string>
- <!-- Notification content to tell the user that emergency service is blocked by access control. -->
- <string name="RestrictedOnEmergencyContent">Your carrier has temporarily suspended emergency calls at this location</string>
- <!-- Notification content to tell the user that normal service is blocked by access control. -->
- <string name="RestrictedOnNormalContent">Your carrier has temporarily suspended voice calls at this location</string>
- <!-- Notification content to tell the user that all emergency and normal voice services are blocked by access control. -->
- <string name="RestrictedOnAllVoiceContent">Your carrier has temporarily suspended voice and emergency calls at this location</string>
+ <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
+ <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
<!-- Displayed to tell the user that they should switch their network preference. -->
<string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8678a3e..7dd4022 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -521,10 +521,7 @@
<java-symbol type="string" name="RestrictedOnDataTitle" />
<java-symbol type="string" name="RestrictedOnEmergencyTitle" />
<java-symbol type="string" name="RestrictedOnNormalTitle" />
- <java-symbol type="string" name="RestrictedOnAllVoiceContent" />
- <java-symbol type="string" name="RestrictedOnDataContent" />
- <java-symbol type="string" name="RestrictedOnEmergencyContent" />
- <java-symbol type="string" name="RestrictedOnNormalContent" />
+ <java-symbol type="string" name="RestrictedStateContent" />
<java-symbol type="string" name="notification_channel_network_alert" />
<java-symbol type="string" name="notification_channel_call_forward" />
<java-symbol type="string" name="notification_channel_emergency_callback" />
@@ -1809,6 +1806,7 @@
<java-symbol type="dimen" name="default_minimal_size_pip_resizable_task" />
<java-symbol type="dimen" name="task_height_of_minimized_mode" />
<java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
+ <java-symbol type="bool" name="config_allowPriorityVibrationsInLowPowerMode" />
<java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
<java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
<java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index e3b4740..f931d21 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1036,6 +1036,8 @@
// old shader's pointer may be reused by another shader allocation later
if (mShader != shader) {
mNativeShader = -1;
+ // Release any native references to the old shader content
+ nSetShader(mNativePaint, 0);
}
// Defer setting the shader natively until getNativeInstance() is called
mShader = shader;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 00b5eda..90d6ab8 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -834,6 +834,16 @@
final Animator localAnimator = animator.clone();
final String targetName = mTargetNameMap.get(animator);
final Object target = mVectorDrawable.getTargetByName(targetName);
+ if (!mShouldIgnoreInvalidAnim) {
+ if (target == null) {
+ throw new IllegalStateException("Target with the name \"" + targetName
+ + "\" cannot be found in the VectorDrawable to be animated.");
+ } else if (!(target instanceof VectorDrawable.VectorDrawableState)
+ && !(target instanceof VectorDrawable.VObject)) {
+ throw new UnsupportedOperationException("Target should be either VGroup, VPath,"
+ + " or ConstantState, " + target.getClass() + " is not supported");
+ }
+ }
localAnimator.setTarget(target);
return localAnimator;
}
@@ -1321,16 +1331,10 @@
throw new IllegalArgumentException("ClipPath only supports PathData " +
"property");
}
-
}
} else if (target instanceof VectorDrawable.VectorDrawableState) {
createRTAnimatorForRootGroup(values, animator,
(VectorDrawable.VectorDrawableState) target, startTime);
- } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
- // Should never get here
- throw new UnsupportedOperationException("Target should be either VGroup, VPath, " +
- "or ConstantState, " + target == null ? "Null target" : target.getClass() +
- " is not supported");
}
}
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index 228a6de..dd731df 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -136,7 +136,13 @@
private void teardownConnection() {
if (mConnection != null) {
- mInputStream = null;
+ if (mInputStream != null) {
+ try {
+ mInputStream.close();
+ } catch (IOException e) {
+ }
+ mInputStream = null;
+ }
mConnection.disconnect();
mConnection = null;
@@ -298,8 +304,7 @@
mCurrentOffset = offset;
} catch (IOException e) {
mTotalSize = -1;
- mInputStream = null;
- mConnection = null;
+ teardownConnection();
mCurrentOffset = -1;
throw e;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index ecbc4f7..9557262 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -140,7 +140,8 @@
if (mState.value) {
mController.setZen(ZEN_MODE_OFF, null, TAG);
} else {
- mController.setZen(ZEN_MODE_ALARMS, null, TAG);
+ int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
+ mController.setZen(zen, null, TAG);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7697061..ba3bcc7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -514,6 +514,9 @@
RecentsActivityLaunchState launchState = config.getLaunchState();
launchState.reset();
}
+
+ // Force a gc to attempt to clean up bitmap references more quickly (b/38258699)
+ Recents.getSystemServices().gc();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index cbfa0e5..1f13830 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -362,6 +362,19 @@
}
/**
+ * Requests a gc() from the background thread.
+ */
+ public void gc() {
+ BackgroundThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ System.gc();
+ System.runFinalization();
+ }
+ });
+ }
+
+ /**
* @return whether the provided {@param className} is blacklisted
*/
public boolean isBlackListedActivity(String className) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 531437d..58844ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -146,12 +146,12 @@
// Construct the icon.
icon = new StatusBarIconView(context,
- sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+ sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
// Construct the expanded icon.
expandedIcon = new StatusBarIconView(context,
- sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+ sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
final StatusBarIcon ic = new StatusBarIcon(
sbn.getUser(),
@@ -187,9 +187,11 @@
* @param n the notification to read the icon from.
* @throws InflationException
*/
- public void updateIcons(Context context, Notification n) throws InflationException {
+ public void updateIcons(Context context, StatusBarNotification sbn)
+ throws InflationException {
if (icon != null) {
// Update the icon
+ Notification n = sbn.getNotification();
final StatusBarIcon ic = new StatusBarIcon(
notification.getUser(),
notification.getPackageName(),
@@ -197,8 +199,8 @@
n.iconLevel,
n.number,
StatusBarIconView.contentDescForNotification(context, n));
- icon.setNotification(n);
- expandedIcon.setNotification(n);
+ icon.setNotification(sbn);
+ expandedIcon.setNotification(sbn);
if (!icon.set(ic) || !expandedIcon.set(ic)) {
throw new InflationException("Couldn't update icon: " + ic);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 85475b6..3c7ddb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -34,6 +34,7 @@
import android.graphics.drawable.Icon;
import android.os.Parcelable;
import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -99,7 +100,7 @@
private int mNumberX;
private int mNumberY;
private String mNumberText;
- private Notification mNotification;
+ private StatusBarNotification mNotification;
private final boolean mBlocked;
private int mDensity;
private float mIconScale = 1.0f;
@@ -127,11 +128,11 @@
};
private final NotificationIconDozeHelper mDozer;
- public StatusBarIconView(Context context, String slot, Notification notification) {
- this(context, slot, notification, false);
+ public StatusBarIconView(Context context, String slot, StatusBarNotification sbn) {
+ this(context, slot, sbn, false);
}
- public StatusBarIconView(Context context, String slot, Notification notification,
+ public StatusBarIconView(Context context, String slot, StatusBarNotification sbn,
boolean blocked) {
super(context);
mDozer = new NotificationIconDozeHelper(context);
@@ -141,7 +142,7 @@
mNumberPain.setTextAlign(Paint.Align.CENTER);
mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
mNumberPain.setAntiAlias(true);
- setNotification(notification);
+ setNotification(sbn);
maybeUpdateIconScaleDimens();
setScaleType(ScaleType.CENTER);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
@@ -207,9 +208,11 @@
}
}
- public void setNotification(Notification notification) {
+ public void setNotification(StatusBarNotification notification) {
mNotification = notification;
- setContentDescription(notification);
+ if (notification != null) {
+ setContentDescription(notification.getNotification());
+ }
}
public StatusBarIconView(Context context, AttributeSet attrs) {
@@ -315,6 +318,10 @@
return true;
}
+ public Icon getSourceIcon() {
+ return mIcon.icon;
+ }
+
private Drawable getIcon(StatusBarIcon icon) {
return getIcon(getContext(), icon);
}
@@ -354,7 +361,7 @@
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
if (mNotification != null) {
- event.setParcelableData(mNotification);
+ event.setParcelableData(mNotification.getNotification());
}
}
@@ -456,6 +463,10 @@
+ " notification=" + mNotification + ")";
}
+ public StatusBarNotification getNotification() {
+ return mNotification;
+ }
+
public String getSlot() {
return mSlot;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 52838b0..5bfdd1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -4,11 +4,15 @@
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.Icon;
import android.support.annotation.NonNull;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
+import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -180,14 +184,54 @@
}
}
+ // In case we are changing the suppression of a group, the replacement shouldn't flicker
+ // and it should just be replaced instead. We therefore look for notifications that were
+ // just replaced by the child or vice-versa to suppress this.
+ ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();
ArrayList<View> toRemove = new ArrayList<>();
for (int i = 0; i < hostLayout.getChildCount(); i++) {
View child = hostLayout.getChildAt(i);
+ if (!(child instanceof StatusBarIconView)) {
+ continue;
+ }
if (!toShow.contains(child)) {
- toRemove.add(child);
+ boolean iconWasReplaced = false;
+ StatusBarIconView removedIcon = (StatusBarIconView) child;
+ String removedGroupKey = removedIcon.getNotification().getGroupKey();
+ for (int j = 0; j < toShow.size(); j++) {
+ StatusBarIconView candidate = toShow.get(j);
+ if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
+ && candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
+ if (!iconWasReplaced) {
+ iconWasReplaced = true;
+ } else {
+ iconWasReplaced = false;
+ break;
+ }
+ }
+ }
+ if (iconWasReplaced) {
+ ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);
+ if (statusBarIcons == null) {
+ statusBarIcons = new ArrayList<>();
+ replacingIcons.put(removedGroupKey, statusBarIcons);
+ }
+ statusBarIcons.add(removedIcon.getStatusBarIcon());
+ }
+ toRemove.add(removedIcon);
}
}
+ // removing all duplicates
+ ArrayList<String> duplicates = new ArrayList<>();
+ for (String key : replacingIcons.keySet()) {
+ ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(key);
+ if (statusBarIcons.size() != 1) {
+ duplicates.add(key);
+ }
+ }
+ replacingIcons.removeAll(duplicates);
+ hostLayout.setReplacingIcons(replacingIcons);
final int toRemoveCount = toRemove.size();
for (int i = 0; i < toRemoveCount; i++) {
@@ -217,6 +261,7 @@
hostLayout.addView(expected, i);
}
hostLayout.setChangingViewPositions(false);
+ hostLayout.setReplacingIcons(null);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index f94bb0c..a4fadc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -21,9 +21,13 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.drawable.Icon;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
import android.util.AttributeSet;
import android.view.View;
+import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
@@ -33,6 +37,7 @@
import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.statusbar.stack.ViewState;
+import java.util.ArrayList;
import java.util.HashMap;
/**
@@ -117,6 +122,7 @@
private float mVisualOverflowAdaption;
private boolean mDisallowNextAnimation;
private boolean mAnimationsEnabled = true;
+ private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -183,11 +189,17 @@
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
+ boolean isReplacingIcon = isReplacingIcon(child);
if (!mChangingViewPositions) {
- mIconStates.put(child, new IconState());
+ IconState v = new IconState();
+ if (isReplacingIcon) {
+ v.justAdded = false;
+ v.justReplaced = true;
+ }
+ mIconStates.put(child, v);
}
int childIndex = indexOfChild(child);
- if (childIndex < getChildCount() - 1
+ if (childIndex < getChildCount() - 1 && !isReplacingIcon
&& mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
if (mAddAnimationStartIndex < 0) {
mAddAnimationStartIndex = childIndex;
@@ -200,13 +212,34 @@
}
}
+ private boolean isReplacingIcon(View child) {
+ if (mReplacingIcons == null) {
+ return false;
+ }
+ if (!(child instanceof StatusBarIconView)) {
+ return false;
+ }
+ StatusBarIconView iconView = (StatusBarIconView) child;
+ Icon sourceIcon = iconView.getSourceIcon();
+ String groupKey = iconView.getNotification().getGroupKey();
+ ArrayList<StatusBarIcon> statusBarIcons = mReplacingIcons.get(groupKey);
+ if (statusBarIcons != null) {
+ StatusBarIcon replacedIcon = statusBarIcons.get(0);
+ if (sourceIcon.sameAs(replacedIcon.icon)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
if (child instanceof StatusBarIconView) {
+ boolean isReplacingIcon = isReplacingIcon(child);
final StatusBarIconView icon = (StatusBarIconView) child;
if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
- && child.getVisibility() == VISIBLE) {
+ && child.getVisibility() == VISIBLE && isReplacingIcon) {
int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
if (mAddAnimationStartIndex < 0) {
mAddAnimationStartIndex = animationStartIndex;
@@ -216,9 +249,11 @@
}
if (!mChangingViewPositions) {
mIconStates.remove(child);
- addTransientView(icon, 0);
- icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
- () -> removeTransientView(icon));
+ if (!isReplacingIcon) {
+ addTransientView(icon, 0);
+ icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
+ () -> removeTransientView(icon));
+ }
}
}
}
@@ -473,11 +508,16 @@
mAnimationsEnabled = enabled;
}
+ public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
+ mReplacingIcons = replacingIcons;
+ }
+
public class IconState extends ViewState {
public float iconAppearAmount = 1.0f;
public float clampedAppearAmount = 1.0f;
public int visibleState;
public boolean justAdded = true;
+ private boolean justReplaced;
public boolean needsCannedAnimation;
public boolean useFullTransitionAmount;
public boolean useLinearTransitionAmount;
@@ -496,9 +536,9 @@
&& !mDisallowNextAnimation
&& !noAnimations;
if (animationsAllowed) {
- if (justAdded) {
+ if (justAdded || justReplaced) {
super.applyToView(icon);
- if (iconAppearAmount != 0.0f) {
+ if (justAdded && iconAppearAmount != 0.0f) {
icon.setAlpha(0.0f);
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN,
false /* animate */);
@@ -557,6 +597,7 @@
}
}
justAdded = false;
+ justReplaced = false;
needsCannedAnimation = false;
justUndarkened = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 1e658d9..f4f48a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -471,6 +471,7 @@
int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
private final Rect mLastFullscreenStackBounds = new Rect();
private final Rect mLastDockedStackBounds = new Rect();
+ private final Rect mTmpRect = new Rect();
// last value sent to window manager
private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
@@ -1371,20 +1372,33 @@
int numChildren = mStackScroller.getChildCount();
final ArrayList<View> viewsToHide = new ArrayList<View>(numChildren);
+ final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren);
for (int i = 0; i < numChildren; i++) {
final View child = mStackScroller.getChildAt(i);
if (child instanceof ExpandableNotificationRow) {
- if (mStackScroller.canChildBeDismissed(child)) {
- if (child.getVisibility() == View.VISIBLE) {
- viewsToHide.add(child);
- }
- }
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ boolean parentVisible = false;
+ boolean hasClipBounds = child.getClipBounds(mTmpRect);
+ if (mStackScroller.canChildBeDismissed(child)) {
+ viewsToRemove.add(row);
+ if (child.getVisibility() == View.VISIBLE
+ && (!hasClipBounds || mTmpRect.height() > 0)) {
+ viewsToHide.add(child);
+ parentVisible = true;
+ }
+ } else if (child.getVisibility() == View.VISIBLE
+ && (!hasClipBounds || mTmpRect.height() > 0)) {
+ parentVisible = true;
+ }
List<ExpandableNotificationRow> children = row.getNotificationChildren();
- if (row.areChildrenExpanded() && children != null) {
+ if (children != null) {
for (ExpandableNotificationRow childRow : children) {
- if (mStackScroller.canChildBeDismissed(childRow)) {
- if (childRow.getVisibility() == View.VISIBLE) {
+ viewsToRemove.add(childRow);
+ if (parentVisible && row.areChildrenExpanded()
+ && mStackScroller.canChildBeDismissed(childRow)) {
+ hasClipBounds = childRow.getClipBounds(mTmpRect);
+ if (childRow.getVisibility() == View.VISIBLE
+ && (!hasClipBounds || mTmpRect.height() > 0)) {
viewsToHide.add(childRow);
}
}
@@ -1392,7 +1406,7 @@
}
}
}
- if (viewsToHide.isEmpty()) {
+ if (viewsToRemove.isEmpty()) {
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
return;
}
@@ -1401,6 +1415,13 @@
@Override
public void run() {
mStackScroller.setDismissAllInProgress(false);
+ for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
+ if (mStackScroller.canChildBeDismissed(rowToRemove)) {
+ removeNotification(rowToRemove.getEntry().key, null);
+ } else {
+ rowToRemove.resetTranslation();
+ }
+ }
try {
mBarService.onClearAllNotifications(mCurrentUserId);
} catch (Exception ex) { }
@@ -6100,6 +6121,9 @@
}
public boolean isLockscreenPublicMode(int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ return mLockscreenPublicMode.get(mCurrentUserId, false);
+ }
return mLockscreenPublicMode.get(userId, false);
}
@@ -6778,7 +6802,7 @@
entry.notification = notification;
mGroupManager.onEntryUpdated(entry, oldNotification);
- entry.updateIcons(mContext, n);
+ entry.updateIcons(mContext, notification);
inflateViews(entry, mStackScroller);
mForegroundServiceController.updateNotification(notification,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 55ec307..db6647c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -72,7 +72,7 @@
NotificationData mNotificationData;
PowerManager mPowerManager;
SystemServicesProxy mSystemServicesProxy;
-
+ NotificationPanelView mNotificationPanelView;
private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@Before
@@ -85,6 +85,7 @@
mHeadsUpManager = mock(HeadsUpManager.class);
mNotificationData = mock(NotificationData.class);
mSystemServicesProxy = mock(SystemServicesProxy.class);
+ mNotificationPanelView = mock(NotificationPanelView.class);
IPowerManager powerManagerService = mock(IPowerManager.class);
HandlerThread handlerThread = new HandlerThread("TestThread");
handlerThread.start();
@@ -95,7 +96,7 @@
mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
- mNotificationData, mPowerManager, mSystemServicesProxy);
+ mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView);
doAnswer(invocation -> {
OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
@@ -287,7 +288,7 @@
public TestableStatusBar(StatusBarKeyguardViewManager man,
UnlockMethodCache unlock, KeyguardIndicationController key,
NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd,
- PowerManager pm, SystemServicesProxy ssp) {
+ PowerManager pm, SystemServicesProxy ssp, NotificationPanelView panelView) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -297,6 +298,7 @@
mUseHeadsUp = true;
mPowerManager = pm;
mSystemServicesProxy = ssp;
+ mNotificationPanel = panelView;
}
@Override
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 980a7d4..073d7b2 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -774,20 +774,29 @@
break;
}
- final AutofillValue currentValue = viewState.getCurrentValue();
- if (currentValue == null || currentValue.isEmpty()) {
- if (sDebug) {
- Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+ AutofillValue value = viewState.getCurrentValue();
+ if (value == null || value.isEmpty()) {
+ final AutofillValue initialValue = getValueFromContexts(id);
+ if (initialValue != null) {
+ if (sDebug) {
+ Slog.d(TAG, "Value of required field " + id + " didn't change; "
+ + "using initial value (" + initialValue + ") instead");
+ }
+ value = initialValue;
+ } else {
+ if (sDebug) {
+ Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+ }
+ allRequiredAreNotEmpty = false;
+ break;
}
- allRequiredAreNotEmpty = false;
- break;
}
final AutofillValue filledValue = viewState.getAutofilledValue();
- if (!currentValue.equals(filledValue)) {
+ if (!value.equals(filledValue)) {
if (sDebug) {
Slog.d(TAG, "showSaveLocked(): found a change on required " + id + ": "
- + filledValue + " => " + currentValue);
+ + filledValue + " => " + value);
}
atLeastOneChanged = true;
}
@@ -845,6 +854,31 @@
}
/**
+ * Gets the latest non-empty value for the given id in the autofill contexts.
+ */
+ @Nullable
+ private AutofillValue getValueFromContexts(AutofillId id) {
+ AutofillValue value = null;
+ final int numContexts = mContexts.size();
+ for (int i = 0; i < numContexts; i++) {
+ final FillContext context = mContexts.get(i);
+ // TODO: create a function that gets just one node so it doesn't create an array
+ // unnecessarily
+ final ViewNode[] nodes = context.findViewNodesByAutofillIds(id);
+ if (nodes != null) {
+ AutofillValue candidate = nodes[0].getAutofillValue();
+ if (sDebug) {
+ Slog.d(TAG, "getValueFromContexts(" + id + ") at " + i + ": " + candidate);
+ }
+ if (candidate != null && !candidate.isEmpty()) {
+ value = candidate;
+ }
+ }
+ }
+ return value;
+ }
+
+ /**
* Calls service when user requested save.
*/
void callSaveLocked() {
@@ -1009,7 +1043,7 @@
|| action == ACTION_VIEW_ENTERED) {
if (sVerbose) Slog.v(TAG, "Creating viewState for " + id + " on " + action);
boolean isIgnored = isIgnoredLocked(id);
- viewState = new ViewState(this, id, value, this,
+ viewState = new ViewState(this, id, this,
isIgnored ? ViewState.STATE_IGNORED : ViewState.STATE_INITIAL);
mViewStates.put(id, viewState);
if (isIgnored) {
@@ -1307,7 +1341,7 @@
if (viewState != null) {
viewState.setState(state);
} else {
- viewState = new ViewState(this, id, null, this, state);
+ viewState = new ViewState(this, id, this, state);
if (sVerbose) {
Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
}
@@ -1370,10 +1404,16 @@
}
}
+ @Override
+ public String toString() {
+ return "Session: [id=" + id + ", pkg=" + mPackageName + "]";
+ }
+
void dumpLocked(String prefix, PrintWriter pw) {
final String prefix2 = prefix + " ";
pw.print(prefix); pw.print("id: "); pw.println(id);
pw.print(prefix); pw.print("uid: "); pw.println(uid);
+ pw.print(prefix); pw.print("mPackagename: "); pw.println(mPackageName);
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("mResponses: ");
if (mResponses == null) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index cd8f4a5..51659bb 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -74,16 +74,14 @@
private final Session mSession;
private FillResponse mResponse;
- private AutofillValue mInitialValue;
private AutofillValue mCurrentValue;
private AutofillValue mAutofilledValue;
private Rect mVirtualBounds;
private int mState;
- ViewState(Session session, AutofillId id, AutofillValue value, Listener listener, int state) {
+ ViewState(Session session, AutofillId id, Listener listener, int state) {
mSession = session;
this.id = id;
- mInitialValue = value;
mListener = listener;
mState = state;
}
@@ -118,11 +116,6 @@
}
@Nullable
- AutofillValue getInitialValue() {
- return mInitialValue;
- }
-
- @Nullable
FillResponse getResponse() {
return mResponse;
}
@@ -189,8 +182,8 @@
@Override
public String toString() {
- return "ViewState: [id=" + id + ", initialValue=" + mInitialValue
- + ", currentValue=" + mCurrentValue + ", autofilledValue=" + mAutofilledValue
+ return "ViewState: [id=" + id + ", currentValue=" + mCurrentValue
+ + ", autofilledValue=" + mAutofilledValue
+ ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() + "]";
}
@@ -207,7 +200,6 @@
pw.println(mResponse.getRequestId());
}
}
- pw.print(prefix); pw.print("initialValue:" ); pw.println(mInitialValue);
pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue);
pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue);
pw.print(prefix); pw.print("virtualBounds:" ); pw.println(mVirtualBounds);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index c3d55054..8ffe8f5 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -332,6 +332,10 @@
@android.annotation.UiThread
private void hideSaveUiUiThread(@Nullable AutoFillUiCallback callback) {
+ if (sVerbose) {
+ Slog.v(TAG, "hideSaveUiUiThread(): mSaveUi=" + mSaveUi + ", callback=" + callback
+ + ", mCallback=" + mCallback);
+ }
if (mSaveUi != null && (callback == null || callback == mCallback)) {
mSaveUi.destroy();
mSaveUi = null;
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d566d3d..e9c98e9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -398,6 +398,12 @@
} catch (WindowManager.BadTokenException e) {
if (sDebug) Slog.d(TAG, "Filed with with token " + params.token + " gone.");
mCallback.onDestroy();
+ } catch (IllegalStateException e) {
+ // WM throws an ISE if mContentView was added twice; this should never happen -
+ // since show() and hide() are always called in the UIThread - but when it does,
+ // it should not crash the system.
+ Slog.e(TAG, "Exception showing window " + params, e);
+ mCallback.onDestroy();
}
}
@@ -405,10 +411,18 @@
* Hides the window.
*/
void hide() {
- if (mShowing) {
- mContentView.setOnTouchListener(null);
- mWm.removeView(mContentView);
- mShowing = false;
+ try {
+ if (mShowing) {
+ mContentView.setOnTouchListener(null);
+ mWm.removeView(mContentView);
+ mShowing = false;
+ }
+ } catch (IllegalStateException e) {
+ // WM might thrown an ISE when removing the mContentView; this should never
+ // happen - since show() and hide() are always called in the UIThread - but if it
+ // does, it should not crash the system.
+ Slog.e(TAG, "Exception hiding window ", e);
+ mCallback.onDestroy();
}
}
@@ -489,7 +503,7 @@
final String value = item.getValue();
// No value, i.e. null, matches any filter
if (value == null
- || value.toLowerCase().contains(constraintLowerCase)) {
+ || value.toLowerCase().startsWith(constraintLowerCase)) {
filteredItems.add(item);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index d25ffce..491af91 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -17,6 +17,7 @@
package com.android.server.autofill.ui;
import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.NonNull;
import android.app.Dialog;
@@ -63,7 +64,7 @@
@Override
public void onSave() {
- if (sDebug) Slog.d(TAG, "onSave(): " + mDone);
+ if (sDebug) Slog.d(TAG, "OneTimeListener.onSave(): " + mDone);
if (mDone) {
return;
}
@@ -73,7 +74,7 @@
@Override
public void onCancel(IntentSender listener) {
- if (sDebug) Slog.d(TAG, "onCancel(): " + mDone);
+ if (sDebug) Slog.d(TAG, "OneTimeListener.onCancel(): " + mDone);
if (mDone) {
return;
}
@@ -83,7 +84,7 @@
@Override
public void onDestroy() {
- if (sDebug) Slog.d(TAG, "onDestroy(): " + mDone);
+ if (sDebug) Slog.d(TAG, "OneTimeListener.onDestroy(): " + mDone);
if (mDone) {
return;
}
@@ -158,9 +159,8 @@
subTitleView.setVisibility(View.VISIBLE);
}
- Slog.i(TAG, "Showing save dialog: " + mTitle);
if (sDebug) {
- Slog.d(TAG, "SubTitle: " + mSubTitle);
+ Slog.d(TAG, "on constructor: title=" + mTitle + ", subTitle=" + mSubTitle);
}
final TextView noButton = view.findViewById(R.id.autofill_save_no);
@@ -169,15 +169,15 @@
} else {
noButton.setText(R.string.autofill_save_no);
}
- noButton.setOnClickListener((v) -> mListener.onCancel(
- info.getNegativeActionListener()));
+ View.OnClickListener cancelListener =
+ (v) -> mListener.onCancel(info.getNegativeActionListener());
+ noButton.setOnClickListener(cancelListener);
final View yesButton = view.findViewById(R.id.autofill_save_yes);
yesButton.setOnClickListener((v) -> mListener.onSave());
final View closeButton = view.findViewById(R.id.autofill_save_close);
- closeButton.setOnClickListener((v) -> mListener.onCancel(
- info.getNegativeActionListener()));
+ closeButton.setOnClickListener(cancelListener);
mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel);
mDialog.setContentView(view);
@@ -195,13 +195,16 @@
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.accessibilityTitle = context.getString(R.string.autofill_save_accessibility_title);
+ Slog.i(TAG, "Showing save dialog: " + mTitle);
mDialog.show();
}
void destroy() {
+ if (sDebug) Slog.d(TAG, "destroy()");
throwIfDestroyed();
mListener.onDestroy();
mHandler.removeCallbacksAndMessages(mListener);
+ if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
mDialog.dismiss();
mDestroyed = true;
}
@@ -212,6 +215,11 @@
}
}
+ @Override
+ public String toString() {
+ return mTitle == null ? "NO TITLE" : mTitle.toString();
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("title: "); pw.println(mTitle);
pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 03e9dd2..16e63b3 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -73,6 +73,7 @@
private final LinkedList<VibrationInfo> mPreviousVibrations;
private final int mPreviousVibrationsLimit;
+ private final boolean mAllowPriorityVibrationsInLowPowerMode;
private final boolean mSupportsAmplitudeControl;
private final int mDefaultVibrationAmplitude;
private final VibrationEffect[] mFallbackEffects;
@@ -213,6 +214,9 @@
mDefaultVibrationAmplitude = mContext.getResources().getInteger(
com.android.internal.R.integer.config_defaultVibrationAmplitude);
+ mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode);
+
mPreviousVibrations = new LinkedList<>();
IntentFilter filter = new IntentFilter();
@@ -456,7 +460,7 @@
}
private void startVibrationLocked(final Vibration vib) {
- if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+ if (!isAllowedToVibrate(vib)) {
if (DEBUG) {
Slog.e(TAG, "Vibrate ignored, low power mode");
}
@@ -505,6 +509,26 @@
}
}
+ private boolean isAllowedToVibrate(Vibration vib) {
+ if (!mLowPowerMode) {
+ return true;
+ }
+ if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+ return true;
+ }
+ if (!mAllowPriorityVibrationsInLowPowerMode) {
+ return false;
+ }
+ if (vib.mUsageHint == AudioAttributes.USAGE_ALARM ||
+ vib.mUsageHint == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY ||
+ vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) {
+
+ return true;
+ }
+
+ return false;
+ }
+
private boolean shouldVibrateForRingtone() {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
int ringerMode = audioManager.getRingerModeInternal();
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index ec4dc64..f0b1b3b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -751,6 +751,11 @@
}
}
+ private boolean isVisible(int visibility) {
+ return visibility == AccountManager.VISIBILITY_VISIBLE ||
+ visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
+ }
+
/**
* Updates visibility for given account name and package.
*
@@ -803,8 +808,10 @@
if (notify) {
for (Entry<String, Integer> packageToVisibility : packagesToVisibility
.entrySet()) {
- if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
- resolveAccountVisibility(account, packageName, accounts))) {
+ int oldVisibility = packageToVisibility.getValue();
+ int currentVisibility =
+ resolveAccountVisibility(account, packageName, accounts);
+ if (isVisible(oldVisibility) != isVisible(currentVisibility)) {
notifyPackage(packageToVisibility.getKey(), accounts);
}
}
@@ -1181,8 +1188,7 @@
for (Entry<String, Integer> packageToVisibility :
packagesToVisibility.entrySet()) {
- if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
- AccountManager.VISIBILITY_NOT_VISIBLE)) {
+ if (isVisible(packageToVisibility.getValue())) {
notifyPackage(packageToVisibility.getKey(), accounts);
}
}
@@ -1218,14 +1224,6 @@
}
}
- private boolean shouldNotifyOnVisibilityChange(int oldVisibility, int newVisibility) {
- boolean oldVisible = (oldVisibility == AccountManager.VISIBILITY_VISIBLE) ||
- (oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
- boolean newVisible = (newVisibility == AccountManager.VISIBILITY_VISIBLE) ||
- (newVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
- return oldVisible == newVisible;
- }
-
private SparseBooleanArray getUidsOfInstalledOrUpdatedPackagesAsUser(int userId) {
// Get the UIDs of all apps that might have data on the device. We want
// to preserve user data if the app might otherwise be storing data.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index bad7091..c417484 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -813,7 +813,8 @@
String title;
String msg;
String[] pkgs;
- long oldestStartTime = System.currentTimeMillis(); // now
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ long oldestStartTime = nowElapsed;
if (active.size() == 1) {
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", active.get(0).mPackageName, null));
@@ -846,8 +847,8 @@
.addExtras(notificationBundle)
.setSmallIcon(R.drawable.stat_sys_vitals)
.setOngoing(true)
- .setShowWhen(oldestStartTime > 0)
- .setWhen(oldestStartTime)
+ .setShowWhen(oldestStartTime < nowElapsed)
+ .setWhen(System.currentTimeMillis() - (nowElapsed - oldestStartTime))
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color))
.setContentTitle(title)
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 1504538..3ca65cd 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1858,7 +1858,7 @@
account.account.name, account.userId, account.account.type);
pw.println("=======================================================================");
- final PrintTable table = new PrintTable(12);
+ final PrintTable table = new PrintTable(13);
table.set(0, 0,
"Authority", // 0
"Syncable", // 1
@@ -1871,7 +1871,8 @@
"User", // 8
"Tot", // 9
"Time", // 10
- "Last Sync" // 11
+ "Last Sync", // 11
+ "Etc" // 12
);
final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
@@ -1921,6 +1922,7 @@
}
}
+ row1 = row;
if (status.lastSuccessTime != 0) {
table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastSuccessSource]
+ " " + "SUCCESS");
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 9862516..e2fd0ac 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -369,8 +369,8 @@
mPendingBacklight = backlight;
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
- mStateChangeInProgress = stateChanged;
- mBacklightChangeInProgress = backlightChanged;
+ mStateChangeInProgress = stateChanged || mStateChangeInProgress;
+ mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
if (!changeInProgress) {
mLock.notifyAll();
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index ac7b763..d1aecb1 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -936,7 +936,7 @@
// permissions if the version on the system image does not declare them.
if (!isDefaultPhoneOrSms && pkg.isUpdatedSystemApp()) {
PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
- if (sysPs != null) {
+ if (sysPs != null && sysPs.pkg != null) {
if (sysPs.pkg.requestedPermissions.isEmpty()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 3a116bb..551e3bf 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -102,6 +102,8 @@
| FLAG_SCALED
| FLAG_SECURE;
+ private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
private static final int MSG_REPORT_DRAW = 0;
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
@@ -160,7 +162,8 @@
layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
| FLAG_NOT_TOUCHABLE;
- layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
+ layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT
+ | (windowPrivateFlags & PRIVATE_FLAG_INHERITS);
layoutParams.token = token.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index eff8ed9..39878cc 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -109,6 +109,7 @@
/** Application tokens that are exiting, but still on screen for animations. */
final AppTokenList mExitingAppTokens = new AppTokenList();
+ final AppTokenList mTmpAppTokens = new AppTokenList();
/** Detach this stack from its display when animation completes. */
// TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -1626,9 +1627,14 @@
// TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
// below but is set in the loop above. See if it really matters...
- final int exitingCount = mExitingAppTokens.size();
- for (int i = 0; i < exitingCount; i++) {
- final AppWindowAnimator appAnimator = mExitingAppTokens.get(i).mAppAnimator;
+
+ // Clear before using.
+ mTmpAppTokens.clear();
+ // We copy the list as things can be removed from the exiting token list while we are
+ // processing.
+ mTmpAppTokens.addAll(mExitingAppTokens);
+ for (int i = 0; i < mTmpAppTokens.size(); i++) {
+ final AppWindowAnimator appAnimator = mTmpAppTokens.get(i).mAppAnimator;
appAnimator.wasAnimating = appAnimator.animating;
if (appAnimator.stepAnimationLocked(currentTime)) {
mService.mAnimator.setAnimating(true);
@@ -1641,6 +1647,8 @@
"updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
}
}
+ // Clear to avoid holding reference to tokens.
+ mTmpAppTokens.clear();
}
@Override