diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-08-21 03:02:17 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-08-21 03:02:17 +0000 |
commit | 44b2fa6114b64125eea887a48c699069b7957eea (patch) | |
tree | 9f09671466054c9961addd773981f101e4617260 | |
parent | 7a1bc135d3c001aa75dfb122d89fae45b0ff92ac (diff) | |
parent | c9443e38944b11d32f63fd87aca2e5ceb5235767 (diff) | |
download | base-44b2fa6114b64125eea887a48c699069b7957eea.tar.gz |
Snap for 4966094 from c9443e38944b11d32f63fd87aca2e5ceb5235767 to pi-qpr1-release
Change-Id: I729e9afd508d1ce9d778f365b017024bda3d7afc
22 files changed, 347 insertions, 115 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index a6d2be0842a7..68e8a52a9c24 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6338,6 +6338,10 @@ public class Activity extends ContextThemeWrapper } void dumpInner(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + if (args != null && args.length > 0 && args[0].equals("--autofill")) { + dumpAutofillManager(prefix, writer); + return; + } writer.print(prefix); writer.print("Local Activity "); writer.print(Integer.toHexString(System.identityHashCode(this))); writer.println(" State:"); @@ -6365,16 +6369,20 @@ public class Activity extends ContextThemeWrapper mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix); + dumpAutofillManager(prefix, writer); + + ResourcesManager.getInstance().dump(prefix, writer); + } + + void dumpAutofillManager(String prefix, PrintWriter writer) { final AutofillManager afm = getAutofillManager(); if (afm != null) { + afm.dump(prefix, writer); writer.print(prefix); writer.print("Autofill Compat Mode: "); writer.println(isAutofillCompatibilityEnabled()); - afm.dump(prefix, writer); } else { writer.print(prefix); writer.println("No AutofillManager"); } - - ResourcesManager.getInstance().dump(prefix, writer); } /** diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 30256b42e6a1..8d0ad33a143e 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -121,10 +121,13 @@ public class ResourcesManager { } } + private static final boolean ENABLE_APK_ASSETS_CACHE = false; + /** * The ApkAssets we are caching and intend to hold strong references to. */ - private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = new LruCache<>(3); + private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = + (ENABLE_APK_ASSETS_CACHE) ? new LruCache<>(3) : null; /** * The ApkAssets that are being referenced in the wild that we can reuse, even if they aren't @@ -310,9 +313,12 @@ public class ResourcesManager { private @NonNull ApkAssets loadApkAssets(String path, boolean sharedLib, boolean overlay) throws IOException { final ApkKey newKey = new ApkKey(path, sharedLib, overlay); - ApkAssets apkAssets = mLoadedApkAssets.get(newKey); - if (apkAssets != null) { - return apkAssets; + ApkAssets apkAssets = null; + if (mLoadedApkAssets != null) { + apkAssets = mLoadedApkAssets.get(newKey); + if (apkAssets != null) { + return apkAssets; + } } // Optimistically check if this ApkAssets exists somewhere else. @@ -320,7 +326,10 @@ public class ResourcesManager { if (apkAssetsRef != null) { apkAssets = apkAssetsRef.get(); if (apkAssets != null) { - mLoadedApkAssets.put(newKey, apkAssets); + if (mLoadedApkAssets != null) { + mLoadedApkAssets.put(newKey, apkAssets); + } + return apkAssets; } else { // Clean up the reference. @@ -335,7 +344,11 @@ public class ResourcesManager { } else { apkAssets = ApkAssets.loadFromPath(path, false /*system*/, sharedLib); } - mLoadedApkAssets.put(newKey, apkAssets); + + if (mLoadedApkAssets != null) { + mLoadedApkAssets.put(newKey, apkAssets); + } + mCachedApkAssets.put(newKey, new WeakReference<>(apkAssets)); return apkAssets; } @@ -434,18 +447,22 @@ public class ResourcesManager { pw.println("ResourcesManager:"); pw.increaseIndent(); - pw.print("cached apks: total="); - pw.print(mLoadedApkAssets.size()); - pw.print(" created="); - pw.print(mLoadedApkAssets.createCount()); - pw.print(" evicted="); - pw.print(mLoadedApkAssets.evictionCount()); - pw.print(" hit="); - pw.print(mLoadedApkAssets.hitCount()); - pw.print(" miss="); - pw.print(mLoadedApkAssets.missCount()); - pw.print(" max="); - pw.print(mLoadedApkAssets.maxSize()); + if (mLoadedApkAssets != null) { + pw.print("cached apks: total="); + pw.print(mLoadedApkAssets.size()); + pw.print(" created="); + pw.print(mLoadedApkAssets.createCount()); + pw.print(" evicted="); + pw.print(mLoadedApkAssets.evictionCount()); + pw.print(" hit="); + pw.print(mLoadedApkAssets.hitCount()); + pw.print(" miss="); + pw.print(mLoadedApkAssets.missCount()); + pw.print(" max="); + pw.print(mLoadedApkAssets.maxSize()); + } else { + pw.print("cached apks: 0 [cache disabled]"); + } pw.println(); pw.print("total apks: "); diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java index 7ab3d8bdd857..5694ca860453 100644 --- a/core/java/android/appwidget/AppWidgetManagerInternal.java +++ b/core/java/android/appwidget/AppWidgetManagerInternal.java @@ -16,12 +16,9 @@ package android.appwidget; -import android.annotation.NonNull; import android.annotation.Nullable; import android.util.ArraySet; -import java.util.Set; - /** * App widget manager local system service interface. * @@ -36,4 +33,13 @@ public abstract class AppWidgetManagerInternal { * @return Whether the UID hosts widgets from the package. */ public abstract @Nullable ArraySet<String> getHostedWidgetPackages(int uid); + + /** + * Execute the widget-related work of unlocking a user. This is intentionally + * invoked just <em>before</em> the boot-completed broadcast is issued, after + * the data-related work of unlock has completed. + * + * @param userId The user that is being unlocked. + */ + public abstract void unlockUser(int userId); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 27ed35c384eb..d21cb3e64b8c 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -2145,7 +2145,11 @@ public final class AutofillManager { pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId); pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked()); pw.print(pfx); pw.print("context: "); pw.println(mContext); - pw.print(pfx); pw.print("client: "); pw.println(getClient()); + final AutofillClient client = getClient(); + if (client != null) { + pw.print(pfx); pw.print("client: "); pw.print(client); + pw.print(" ("); pw.print(client.autofillClientGetActivityToken()); pw.println(')'); + } pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); @@ -2164,8 +2168,24 @@ public final class AutofillManager { pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds); pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId); pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish); - pw.print(pfx); pw.print("compat mode enabled: "); pw.println( - isCompatibilityModeEnabledLocked()); + pw.print(pfx); pw.print("compat mode enabled: "); + synchronized (mLock) { + if (mCompatibilityBridge != null) { + final String pfx2 = pfx + " "; + pw.println("true"); + pw.print(pfx2); pw.print("windowId: "); + pw.println(mCompatibilityBridge.mFocusedWindowId); + pw.print(pfx2); pw.print("nodeId: "); + pw.println(mCompatibilityBridge.mFocusedNodeId); + pw.print(pfx2); pw.print("virtualId: "); + pw.println(AccessibilityNodeInfo + .getVirtualDescendantId(mCompatibilityBridge.mFocusedNodeId)); + pw.print(pfx2); pw.print("focusedBounds: "); + pw.println(mCompatibilityBridge.mFocusedBounds); + } else { + pw.println("false"); + } + } pw.print(pfx); pw.print("debug: "); pw.print(sDebug); pw.print(" verbose: "); pw.println(sVerbose); } @@ -2299,7 +2319,15 @@ public final class AutofillManager { @Override public AccessibilityEvent onAccessibilityEvent(AccessibilityEvent event, boolean accessibilityEnabled, int relevantEventTypes) { - switch (event.getEventType()) { + final int type = event.getEventType(); + if (sVerbose) { + // NOTE: this is waaay spammy, but that's life. + Log.v(TAG, "onAccessibilityEvent(" + AccessibilityEvent.eventTypeToString(type) + + "): virtualId=" + + AccessibilityNodeInfo.getVirtualDescendantId(event.getSourceNodeId()) + + ", client=" + getClient()); + } + switch (type) { case AccessibilityEvent.TYPE_VIEW_FOCUSED: { synchronized (mLock) { if (mFocusedWindowId == event.getWindowId() diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index 61f7fe8dc019..bf4374acf6e6 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -43,7 +43,7 @@ public interface QSTile { boolean isAvailable(); void setTileSpec(String tileSpec); - void clearState(); + @Deprecated default void clearState() {} void refreshState(); void addCallback(Callback callback); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 194679cc626e..71cf9b52a2db 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -39,10 +39,13 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.DisplayManager; +import android.os.Handler; +import android.os.HandlerThread; import android.os.SystemProperties; import android.provider.Settings.Secure; import android.support.annotation.VisibleForTesting; import android.util.DisplayMetrics; +import android.util.Log; import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; @@ -57,6 +60,7 @@ import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; +import com.android.internal.util.Preconditions; import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentHostManager.FragmentListener; @@ -74,6 +78,9 @@ import com.android.systemui.util.leak.RotationUtils; * for antialiasing and emulation purposes. */ public class ScreenDecorations extends SystemUI implements Tunable { + private static final boolean DEBUG = false; + private static final String TAG = "ScreenDecorations"; + public static final String SIZE = "sysui_rounded_size"; public static final String PADDING = "sysui_rounded_content_padding"; private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS = @@ -93,9 +100,24 @@ public class ScreenDecorations extends SystemUI implements Tunable { private DisplayCutoutView mCutoutTop; private DisplayCutoutView mCutoutBottom; private boolean mPendingRotationChange; + private Handler mHandler; @Override public void start() { + mHandler = startHandlerThread(); + mHandler.post(this::startOnScreenDecorationsThread); + setupStatusBarPaddingIfNeeded(); + } + + @VisibleForTesting + Handler startHandlerThread() { + HandlerThread thread = new HandlerThread("ScreenDecorations"); + thread.start(); + return thread.getThreadHandler(); + } + + private void startOnScreenDecorationsThread() { + mRotation = RotationUtils.getExactRotation(mContext); mWindowManager = mContext.getSystemService(WindowManager.class); mRoundedDefault = mContext.getResources().getDimensionPixelSize( R.dimen.rounded_corner_radius); @@ -107,12 +129,6 @@ public class ScreenDecorations extends SystemUI implements Tunable { setupDecorations(); } - int padding = mContext.getResources().getDimensionPixelSize( - R.dimen.rounded_corner_content_padding); - if (padding != 0) { - setupPadding(padding); - } - mDisplayListener = new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) { @@ -126,8 +142,8 @@ public class ScreenDecorations extends SystemUI implements Tunable { @Override public void onDisplayChanged(int displayId) { - if (mOverlay != null && mBottomOverlay != null - && mRotation != RotationUtils.getExactRotation(mContext)) { + final int newRotation = RotationUtils.getExactRotation(mContext); + if (mOverlay != null && mBottomOverlay != null && mRotation != newRotation) { // We cannot immediately update the orientation. Otherwise // WindowManager is still deferring layout until it has finished dispatching // the config changes, which may cause divergence between what we draw @@ -136,20 +152,24 @@ public class ScreenDecorations extends SystemUI implements Tunable { // - we are trying to redraw. This because WM resized our window and told us to. // - the config change has been dispatched, so WM is no longer deferring layout. mPendingRotationChange = true; + if (DEBUG) { + Log.i(TAG, "Rotation changed, deferring " + newRotation + ", staying at " + + mRotation); + } + mOverlay.getViewTreeObserver().addOnPreDrawListener( - new RestartingPreDrawListener(mOverlay)); + new RestartingPreDrawListener(mOverlay, newRotation)); mBottomOverlay.getViewTreeObserver().addOnPreDrawListener( - new RestartingPreDrawListener(mBottomOverlay)); - + new RestartingPreDrawListener(mBottomOverlay, newRotation)); } updateOrientation(); } }; - mRotation = -1; mDisplayManager = (DisplayManager) mContext.getSystemService( Context.DISPLAY_SERVICE); - mDisplayManager.registerDisplayListener(mDisplayListener, null); + mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); + updateOrientation(); } private void setupDecorations() { @@ -179,10 +199,11 @@ public class ScreenDecorations extends SystemUI implements Tunable { mWindowManager.getDefaultDisplay().getMetrics(metrics); mDensity = metrics.density; - Dependency.get(TunerService.class).addTunable(this, SIZE); + Dependency.get(Dependency.MAIN_HANDLER).post( + () -> Dependency.get(TunerService.class).addTunable(this, SIZE)); // Watch color inversion and invert the overlay as needed. - SecureSetting setting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER), + SecureSetting setting = new SecureSetting(mContext, mHandler, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) { @Override protected void handleValueChanged(int value, boolean observedChange) { @@ -215,18 +236,37 @@ public class ScreenDecorations extends SystemUI implements Tunable { .start(); } }); + + mOverlay.getViewTreeObserver().addOnPreDrawListener( + new ValidatingPreDrawListener(mOverlay)); + mBottomOverlay.getViewTreeObserver().addOnPreDrawListener( + new ValidatingPreDrawListener(mBottomOverlay)); } @Override protected void onConfigurationChanged(Configuration newConfig) { - mPendingRotationChange = false; - updateOrientation(); - if (shouldDrawCutout() && mOverlay == null) { - setupDecorations(); - } + mHandler.post(() -> { + int oldRotation = mRotation; + mPendingRotationChange = false; + updateOrientation(); + if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation); + if (shouldDrawCutout() && mOverlay == null) { + setupDecorations(); + } + if (mOverlay != null) { + // Updating the layout params ensures that ViewRootImpl will call relayoutWindow(), + // which ensures that the forced seamless rotation will end, even if we updated + // the rotation before window manager was ready (and was still waiting for sending + // the updated rotation). + updateLayoutParams(); + } + }); } - protected void updateOrientation() { + private void updateOrientation() { + Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(), + "must call on " + mHandler.getLooper().getThread() + + ", but was " + Thread.currentThread()); if (mPendingRotationChange) { return; } @@ -306,7 +346,19 @@ public class ScreenDecorations extends SystemUI implements Tunable { com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout); } - private void setupPadding(int padding) { + + private void setupStatusBarPaddingIfNeeded() { + // TODO: This should be moved to a more appropriate place, as it is not related to the + // screen decorations overlay. + int padding = mContext.getResources().getDimensionPixelSize( + R.dimen.rounded_corner_content_padding); + if (padding != 0) { + setupStatusBarPadding(padding); + } + + } + + private void setupStatusBarPadding(int padding) { // Add some padding to all the content near the edge of the screen. StatusBar sb = getComponent(StatusBar.class); View statusBar = (sb != null ? sb.getStatusBarWindow() : null); @@ -375,30 +427,32 @@ public class ScreenDecorations extends SystemUI implements Tunable { @Override public void onTuningChanged(String key, String newValue) { - if (mOverlay == null) return; - if (SIZE.equals(key)) { - int size = mRoundedDefault; - int sizeTop = mRoundedDefaultTop; - int sizeBottom = mRoundedDefaultBottom; - if (newValue != null) { - try { - size = (int) (Integer.parseInt(newValue) * mDensity); - } catch (Exception e) { + mHandler.post(() -> { + if (mOverlay == null) return; + if (SIZE.equals(key)) { + int size = mRoundedDefault; + int sizeTop = mRoundedDefaultTop; + int sizeBottom = mRoundedDefaultBottom; + if (newValue != null) { + try { + size = (int) (Integer.parseInt(newValue) * mDensity); + } catch (Exception e) { + } } - } - if (sizeTop == 0) { - sizeTop = size; - } - if (sizeBottom == 0) { - sizeBottom = size; - } + if (sizeTop == 0) { + sizeTop = size; + } + if (sizeBottom == 0) { + sizeBottom = size; + } - setSize(mOverlay.findViewById(R.id.left), sizeTop); - setSize(mOverlay.findViewById(R.id.right), sizeTop); - setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom); - setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom); - } + setSize(mOverlay.findViewById(R.id.left), sizeTop); + setSize(mOverlay.findViewById(R.id.right), sizeTop); + setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom); + setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom); + } + }); } private void setSize(View view, int pixelSize) { @@ -457,6 +511,11 @@ public class ScreenDecorations extends SystemUI implements Tunable { mVisibilityChangedListener = visibilityChangedListener; mDecorations = decorations; setId(R.id.display_cutout); + if (DEBUG) { + getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG, + (mInitialStart ? "OverlayTop" : "OverlayBottom") + + " drawn in rot " + mRotation)); + } } public void setColor(int color) { @@ -692,20 +751,66 @@ public class ScreenDecorations extends SystemUI implements Tunable { private class RestartingPreDrawListener implements ViewTreeObserver.OnPreDrawListener { private final View mView; + private final int mTargetRotation; - private RestartingPreDrawListener(View view) { + private RestartingPreDrawListener(View view, int targetRotation) { mView = view; + mTargetRotation = targetRotation; } @Override public boolean onPreDraw() { - mPendingRotationChange = false; mView.getViewTreeObserver().removeOnPreDrawListener(this); + + if (mTargetRotation == mRotation) { + if (DEBUG) { + Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom") + + " already in target rot " + + mTargetRotation + ", allow draw without restarting it"); + } + return true; + } + + mPendingRotationChange = false; // This changes the window attributes - we need to restart the traversal for them to // take effect. updateOrientation(); + if (DEBUG) { + Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom") + + " restarting listener fired, restarting draw for rot " + mRotation); + } mView.invalidate(); return false; } } + + /** + * A pre-draw listener, that validates that the rotation we draw in matches the displays + * rotation before continuing the draw. + * + * This is to prevent a race condition, where we have not received the display changed event + * yet, and would thus draw in an old orientation. + */ + private class ValidatingPreDrawListener implements ViewTreeObserver.OnPreDrawListener { + + private final View mView; + + public ValidatingPreDrawListener(View view) { + mView = view; + } + + @Override + public boolean onPreDraw() { + final int displayRotation = RotationUtils.getExactRotation(mContext); + if (displayRotation != mRotation && !mPendingRotationChange) { + if (DEBUG) { + Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot " + + displayRotation + ". Restarting draw"); + } + mView.invalidate(); + return false; + } + return true; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 0876a5d3f456..3fc258b1e8e9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -285,9 +285,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne updatePageIndicator(); - for (TileRecord r : mRecords) { - r.tile.clearState(); - } if (mListening) { refreshAllTiles(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java index 53a576d3519d..591e9e015897 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java @@ -95,7 +95,6 @@ public class TileQueryHelper { continue; } tile.setListening(this, true); - tile.clearState(); tile.refreshState(); tile.setListening(this, false); tile.setTileSpec(spec); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 834feb7781ea..022a2b4a5fbf 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -211,10 +211,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { mHandler.obtainMessage(H.REFRESH_STATE, arg).sendToTarget(); } - public void clearState() { - mHandler.sendEmptyMessage(H.CLEAR_STATE); - } - public void userSwitch(int newUserId) { mHandler.obtainMessage(H.USER_SWITCH, newUserId, 0).sendToTarget(); } @@ -266,11 +262,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { public abstract Intent getLongClickIntent(); - protected void handleClearState() { - mTmpState = newTileState(); - mState = newTileState(); - } - protected void handleRefreshState(Object arg) { handleUpdateState(mTmpState, arg); final boolean changed = mTmpState.copyTo(mState); @@ -409,11 +400,10 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { private static final int TOGGLE_STATE_CHANGED = 8; private static final int SCAN_STATE_CHANGED = 9; private static final int DESTROY = 10; - private static final int CLEAR_STATE = 11; - private static final int REMOVE_CALLBACKS = 12; - private static final int REMOVE_CALLBACK = 13; - private static final int SET_LISTENING = 14; - private static final int STALE = 15; + private static final int REMOVE_CALLBACKS = 11; + private static final int REMOVE_CALLBACK = 12; + private static final int SET_LISTENING = 13; + private static final int STALE = 14; @VisibleForTesting protected H(Looper looper) { @@ -467,9 +457,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { } else if (msg.what == DESTROY) { name = "handleDestroy"; handleDestroy(); - } else if (msg.what == CLEAR_STATE) { - name = "handleClearState"; - handleClearState(); } else if (msg.what == SET_LISTENING) { name = "handleSetListeningInternal"; handleSetListeningInternal(msg.obj, msg.arg1 != 0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java index 06f26c9cbc7c..469c3c2c60b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java @@ -667,9 +667,15 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. entry.row.getNotificationChildren(); for (int i = 0; i < notificationChildren.size(); i++) { ExpandableNotificationRow row = notificationChildren.get(i); - if ((row.getStatusBarNotification().getNotification().flags - & Notification.FLAG_FOREGROUND_SERVICE) != 0) { - // the child is a foreground service notification which we can't remove! + NotificationData.Entry childEntry = row.getEntry(); + boolean isForeground = (row.getStatusBarNotification().getNotification().flags + & Notification.FLAG_FOREGROUND_SERVICE) != 0; + boolean keepForReply = FORCE_REMOTE_INPUT_HISTORY + && (shouldKeepForRemoteInput(childEntry) + || shouldKeepForSmartReply(childEntry)); + if (isForeground || keepForReply) { + // the child is a foreground service notification which we can't remove or it's + // a child we're keeping around for reply! continue; } row.setKeepInParent(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java index af1d220f46f5..48ffe81fdd03 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java @@ -189,7 +189,7 @@ public class QuickStepController implements GestureHelper { mNavigationBarView.getDownHitTarget() == HIT_TARGET_DEAD_ZONE; if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled() && !mNavigationBarView.isQuickStepSwipeUpEnabled())) { - return false; + return deadZoneConsumed; } mNavigationBarView.requestUnbufferedDispatch(event); diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index f1bf31d7a58a..644c0b347bde 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -34,8 +34,10 @@ import static org.mockito.Mockito.when; import android.app.Fragment; import android.content.res.Configuration; +import android.os.Handler; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.Display; import android.view.View; @@ -60,6 +62,7 @@ import org.junit.runner.RunWith; @SmallTest public class ScreenDecorationsTest extends SysuiTestCase { + private TestableLooper mTestableLooper; private ScreenDecorations mScreenDecorations; private StatusBar mStatusBar; private WindowManager mWindowManager; @@ -71,6 +74,10 @@ public class ScreenDecorationsTest extends SysuiTestCase { @Before public void setup() { + mTestableLooper = TestableLooper.get(this); + mDependency.injectTestDependency(Dependency.MAIN_HANDLER, + new Handler(mTestableLooper.getLooper())); + mStatusBar = mock(StatusBar.class); mWindowManager = mock(WindowManager.class); mView = spy(new StatusBarWindowView(mContext, null)); @@ -88,7 +95,31 @@ public class ScreenDecorationsTest extends SysuiTestCase { mTunerService = mDependency.injectMockDependency(TunerService.class); - mScreenDecorations = new ScreenDecorations(); + + mScreenDecorations = new ScreenDecorations() { + @Override + public void start() { + super.start(); + mTestableLooper.processAllMessages(); + } + + @Override + Handler startHandlerThread() { + return new Handler(mTestableLooper.getLooper()); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mTestableLooper.processAllMessages(); + } + + @Override + public void onTuningChanged(String key, String newValue) { + super.onTuningChanged(key, newValue); + mTestableLooper.processAllMessages(); + } + }; mScreenDecorations.mContext = mContext; mScreenDecorations.mComponents = mContext.getComponents(); diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java index c9c7adc45697..f69b6387a605 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java @@ -48,11 +48,6 @@ public class AppWidgetService extends SystemService { } @Override - public void onUnlockUser(int userHandle) { - FgThread.getHandler().post(() -> mImpl.onUserUnlocked(userHandle)); - } - - @Override public void onStopUser(int userHandle) { mImpl.onUserStopped(userHandle); } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index db8ad12cfdf8..b71d7a726b28 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -19,7 +19,6 @@ package com.android.server.appwidget; import static android.content.Context.KEYGUARD_SERVICE; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; - import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import android.annotation.UserIdInt; @@ -2697,7 +2696,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } - void onUserUnlocked(int userId) { + /** + * This does not use the usual onUserUnlocked() listener mechanism because it is + * invoked at a choreographed point in the middle of the user unlock sequence, + * before the boot-completed broadcast is issued and the listeners notified. + */ + void handleUserUnlocked(int userId) { if (isProfileWithLockedParent(userId)) { return; } @@ -2734,7 +2738,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } } - Slog.i(TAG, "Async processing of onUserUnlocked u" + userId + " took " + Slog.i(TAG, "Processing of handleUserUnlocked u" + userId + " took " + (SystemClock.elapsedRealtime() - time) + " ms"); } @@ -4801,5 +4805,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku return widgetPackages; } } + + @Override + public void unlockUser(int userId) { + handleUserUnlocked(userId); + } + } } 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 dc84498353ea..58823036212d 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -81,6 +81,13 @@ final class SaveUi { void onDestroy(); } + /** + * Wrapper that guarantees that only one callback is triggered by ignoring further calls after + * it's destroyed. + * + * <p>It's needed becase {@link #onCancel(IntentSender)} is always called when the Save UI + * dialog is dismissed. + */ private class OneTimeListener implements OnSaveListener { private final OnSaveListener mRealListener; @@ -96,7 +103,6 @@ final class SaveUi { if (mDone) { return; } - mDone = true; mRealListener.onSave(); } @@ -106,7 +112,6 @@ final class SaveUi { if (mDone) { return; } - mDone = true; mRealListener.onCancel(listener); } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index dc9a5adb5a0c..093bd87813d5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2844,6 +2844,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" --checkin: output checkin format, resetting data."); pw.println(" --C: output checkin format, not resetting data."); pw.println(" --proto: output dump in protocol buffer format."); + pw.println(" --autofill: dump just the autofill-related state of an activity"); } else { pw.println("Activity manager (activity) commands:"); pw.println(" help"); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 75f27231c976..60f79f720242 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -694,9 +694,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null; if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) { // Picture-in-picture mode changes also trigger a multi-window mode change as well, so - // update that here in order + // update that here in order. Set the last reported MW state to the same as the PiP + // state since we haven't yet actually resized the task (these callbacks need to + // preceed the configuration change from the resiez. + // TODO(110009072): Once we move these callbacks to the client, remove all logic related + // to forcing the update of the picture-in-picture mode as a part of the PiP animation. mLastReportedPictureInPictureMode = inPictureInPictureMode; - mLastReportedMultiWindowMode = inMultiWindowMode(); + mLastReportedMultiWindowMode = inPictureInPictureMode; final Configuration newConfig = task.computeNewOverrideConfigurationForBounds( targetStackBounds, null); schedulePictureInPictureModeChanged(newConfig); diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 18c095725b09..415a822e3160 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -24,7 +24,6 @@ import static android.app.ActivityManager.USER_OP_IS_CURRENT; import static android.app.ActivityManager.USER_OP_SUCCESS; import static android.os.Process.SHELL_UID; import static android.os.Process.SYSTEM_UID; - import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -48,6 +47,7 @@ import android.app.IStopUserCallback; import android.app.IUserSwitchObserver; import android.app.KeyguardManager; import android.app.usage.UsageEvents; +import android.appwidget.AppWidgetManagerInternal; import android.content.Context; import android.content.IIntentReceiver; import android.content.Intent; @@ -87,8 +87,8 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TimingsTraceLog; import android.util.proto.ProtoOutputStream; - import android.view.Window; + import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -533,6 +533,9 @@ class UserController implements Handler.Callback { } } + // Spin up app widgets prior to boot-complete, so they can be ready promptly + mInjector.startUserWidgets(userId); + Slog.i(TAG, "Sending BOOT_COMPLETE user #" + userId); // Do not report secondary users, runtime restarts or first boot/upgrade if (userId == UserHandle.USER_SYSTEM @@ -2173,6 +2176,13 @@ class UserController implements Handler.Callback { } } + void startUserWidgets(int userId) { + AppWidgetManagerInternal awm = LocalServices.getService(AppWidgetManagerInternal.class); + if (awm != null) { + awm.unlockUser(userId); + } + } + void updateUserConfiguration() { synchronized (mService) { mService.updateUserConfigurationLocked(); diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index b2a12bef5283..86f328d248db 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -31,11 +31,13 @@ import android.os.IBinder; import android.os.Debug; import android.util.ArrayMap; import android.util.Slog; +import android.view.Choreographer; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -112,6 +114,7 @@ public class BoundsAnimationController { private final Interpolator mFastOutSlowInInterpolator; private boolean mFinishAnimationAfterTransition = false; private final AnimationHandler mAnimationHandler; + private Choreographer mChoreographer; private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000; @@ -123,6 +126,12 @@ public class BoundsAnimationController { mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); mAnimationHandler = animationHandler; + if (animationHandler != null) { + // If an animation handler is provided, then ensure that it runs on the sf vsync tick + handler.runWithScissors(() -> mChoreographer = Choreographer.getSfInstance(), + 0 /* timeout */); + animationHandler.setProvider(new SfVsyncFrameCallbackProvider(mChoreographer)); + } } @VisibleForTesting diff --git a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java index bebc5656c284..efb43a6b90cf 100644 --- a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java +++ b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java @@ -21,6 +21,7 @@ import static android.view.Surface.ROTATION_90; import android.graphics.Matrix; import android.view.DisplayInfo; +import android.view.Surface.Rotation; import com.android.server.wm.utils.CoordinateTransforms; @@ -65,6 +66,16 @@ public class ForcedSeamlessRotator { } /** + * Returns the rotation of the display before it started rotating. + * + * @return the old rotation of the display + */ + @Rotation + public int getOldRotation() { + return mOldRotation; + } + + /** * Removes the transform to the window token's surface that undoes the effect of the global * display rotation. * diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c4a0a6961136..8b4a2dd36e6c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1005,7 +1005,6 @@ public class WindowManagerService extends IWindowManager.Stub mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier); final AnimationHandler animationHandler = new AnimationHandler(); - animationHandler.setProvider(new SfVsyncFrameCallbackProvider()); mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition, AnimationThread.getHandler(), animationHandler); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 009f3930d02e..1ae680f793ca 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -681,6 +681,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void forceSeamlesslyRotateIfAllowed(int oldRotation, int rotation) { if (mForceSeamlesslyRotate) { + if (mPendingForcedSeamlessRotate != null) { + oldRotation = mPendingForcedSeamlessRotate.getOldRotation(); + } + mPendingForcedSeamlessRotate = new ForcedSeamlessRotator( oldRotation, rotation, getDisplayInfo()); mPendingForcedSeamlessRotate.unrotate(this.mToken); |