diff options
31 files changed, 380 insertions, 108 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4db1f71e8256..1397f5ea10dc 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2721,10 +2721,13 @@ class ContextImpl extends Context { // need to override their display in ResourcesManager. baseContext.mForceDisplayOverrideInResources = false; baseContext.mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; - baseContext.mDisplay = display; final Resources windowContextResources = createWindowContextResources(baseContext); baseContext.setResources(windowContextResources); + // Associate the display with window context resources so that configuration update from + // the server side will also apply to the display's metrics. + baseContext.mDisplay = ResourcesManager.getInstance() + .getAdjustedDisplay(display.getDisplayId(), windowContextResources); return baseContext; } diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 063ba1174cdc..2e94dd1a47c4 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -143,7 +143,7 @@ public class AppWidgetProviderInfo implements Parcelable { public ComponentName provider; /** - * The default height of the widget when added to a host, in dp. The widget will get + * The default height of the widget when added to a host, in px. The widget will get * at least this width, and will often be given more, depending on the host. * * <p>This field corresponds to the <code>android:minWidth</code> attribute in @@ -152,7 +152,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minWidth; /** - * The default height of the widget when added to a host, in dp. The widget will get + * The default height of the widget when added to a host, in px. The widget will get * at least this height, and will often be given more, depending on the host. * * <p>This field corresponds to the <code>android:minHeight</code> attribute in @@ -161,7 +161,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minHeight; /** - * Minimum width (in dp) which the widget can be resized to. This field has no effect if it + * Minimum width (in px) which the widget can be resized to. This field has no effect if it * is greater than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:minResizeWidth</code> attribute in @@ -170,7 +170,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minResizeWidth; /** - * Minimum height (in dp) which the widget can be resized to. This field has no effect if it + * Minimum height (in px) which the widget can be resized to. This field has no effect if it * is greater than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:minResizeHeight</code> attribute in @@ -179,7 +179,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int minResizeHeight; /** - * Maximum width (in dp) which the widget can be resized to. This field has no effect if it is + * Maximum width (in px) which the widget can be resized to. This field has no effect if it is * smaller than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:maxResizeWidth</code> attribute in the @@ -189,7 +189,7 @@ public class AppWidgetProviderInfo implements Parcelable { public int maxResizeWidth; /** - * Maximum height (in dp) which the widget can be resized to. This field has no effect if it is + * Maximum height (in px) which the widget can be resized to. This field has no effect if it is * smaller than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}). * * <p>This field corresponds to the <code>android:maxResizeHeight</code> attribute in the diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 8e4a68e52697..40041486f6a6 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -436,7 +436,7 @@ public class StatusBarNotification implements Parcelable { try { ApplicationInfo ai = context.getPackageManager() .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, - getUserId()); + getNormalizedUserId()); mContext = context.createApplicationContext(ai, Context.CONTEXT_RESTRICTED); } catch (PackageManager.NameNotFoundException e) { diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 802163617b3b..a7ecf1f2a81d 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -814,9 +814,10 @@ interface IWindowManager * @param displayId The display associated with the window context * @param options A bundle used to pass window-related options and choose the right DisplayArea * - * @return {@code true} if the WindowContext is attached to the DisplayArea successfully. + * @return the DisplayArea's {@link android.app.res.Configuration} if the WindowContext is + * attached to the DisplayArea successfully. {@code null}, otherwise. */ - boolean attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId, + Configuration attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId, in Bundle options); /** diff --git a/core/java/android/window/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl index 8b8dba89ea67..69bc1b5f7763 100644 --- a/core/java/android/window/ITaskOrganizer.aidl +++ b/core/java/android/window/ITaskOrganizer.aidl @@ -88,4 +88,9 @@ oneway interface ITaskOrganizer { * user has pressed back on the root activity of a task controlled by the task organizer. */ void onBackPressedOnTaskRoot(in ActivityManager.RunningTaskInfo taskInfo); + + /** + * Called when the IME has drawn on the organized task. + */ + void onImeDrawnOnTask(int taskId); } diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index c7c91cdd0941..d8723a821a22 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -144,6 +144,10 @@ public class TaskOrganizer extends WindowOrganizer { @BinderThread public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {} + /** @hide */ + @BinderThread + public void onImeDrawnOnTask(int taskId) {} + /** * Creates a persistent root task in WM for a particular windowing-mode. * @param displayId The display to create the root task on. @@ -287,6 +291,11 @@ public class TaskOrganizer extends WindowOrganizer { public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) { mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info)); } + + @Override + public void onImeDrawnOnTask(int taskId) { + mExecutor.execute(() -> TaskOrganizer.this.onImeDrawnOnTask(taskId)); + } }; private ITaskOrganizerController getController() { diff --git a/core/java/android/window/WindowContext.java b/core/java/android/window/WindowContext.java index 901625b0732c..6d0a6bd559ae 100644 --- a/core/java/android/window/WindowContext.java +++ b/core/java/android/window/WindowContext.java @@ -26,7 +26,6 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.res.Configuration; import android.os.Bundle; -import android.os.IBinder; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; @@ -67,7 +66,7 @@ public class WindowContext extends ContextWrapper { mType = type; mOptions = options; mWindowManager = createWindowContextWindowManager(this); - IBinder token = getWindowContextToken(); + WindowTokenClient token = (WindowTokenClient) getWindowContextToken(); mController = new WindowContextController(token); Reference.reachabilityFence(this); diff --git a/core/java/android/window/WindowContextController.java b/core/java/android/window/WindowContextController.java index d84f571931fd..505b45008663 100644 --- a/core/java/android/window/WindowContextController.java +++ b/core/java/android/window/WindowContextController.java @@ -19,6 +19,7 @@ package android.window; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -46,7 +47,7 @@ public class WindowContextController { @VisibleForTesting public boolean mAttachedToDisplayArea; @NonNull - private final IBinder mToken; + private final WindowTokenClient mToken; /** * Window Context Controller constructor @@ -54,14 +55,13 @@ public class WindowContextController { * @param token The token used to attach to a window manager node. It is usually from * {@link Context#getWindowContextToken()}. */ - public WindowContextController(@NonNull IBinder token) { - mToken = token; - mWms = WindowManagerGlobal.getWindowManagerService(); + public WindowContextController(@NonNull WindowTokenClient token) { + this(token, WindowManagerGlobal.getWindowManagerService()); } /** Used for test only. DO NOT USE it in production code. */ @VisibleForTesting - public WindowContextController(@NonNull IBinder token, IWindowManager mockWms) { + public WindowContextController(@NonNull WindowTokenClient token, IWindowManager mockWms) { mToken = token; mWms = mockWms; } @@ -81,8 +81,14 @@ public class WindowContextController { + "a DisplayArea once."); } try { - mAttachedToDisplayArea = mWms.attachWindowContextToDisplayArea(mToken, type, displayId, - options); + final Configuration configuration = mWms.attachWindowContextToDisplayArea(mToken, type, + displayId, options); + if (configuration != null) { + mAttachedToDisplayArea = true; + // Send the DisplayArea's configuration to WindowContext directly instead of + // waiting for dispatching from WMS. + mToken.onConfigurationChanged(configuration, displayId); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java index 6abf5575d353..4dcd2e74a53f 100644 --- a/core/java/android/window/WindowTokenClient.java +++ b/core/java/android/window/WindowTokenClient.java @@ -24,6 +24,8 @@ import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; +import com.android.internal.annotations.VisibleForTesting; + import java.lang.ref.WeakReference; /** @@ -33,7 +35,7 @@ import java.lang.ref.WeakReference; * {@link Context#getWindowContextToken() the token of non-Activity UI Contexts}. * * @see WindowContext - * @see android.view.IWindowManager#registerWindowContextListener(IBinder, int, int, Bundle) + * @see android.view.IWindowManager#attachWindowContextToDisplayArea(IBinder, int, int, Bundle) * * @hide */ @@ -50,8 +52,8 @@ public class WindowTokenClient extends IWindowToken.Stub { * Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient} * can only attach one {@link Context}. * <p>This method must be called before invoking - * {@link android.view.IWindowManager#registerWindowContextListener(IBinder, int, int, - * Bundle, boolean)}.<p/> + * {@link android.view.IWindowManager#attachWindowContextToDisplayArea(IBinder, int, int, + * Bundle)}.<p/> * * @param context context to be attached * @throws IllegalStateException if attached context has already existed. @@ -63,6 +65,13 @@ public class WindowTokenClient extends IWindowToken.Stub { mContextRef = new WeakReference<>(context); } + /** + * Called when {@link Configuration} updates from the server side receive. + * + * @param newConfig the updated {@link Configuration} + * @param newDisplayId the updated {@link android.view.Display} ID + */ + @VisibleForTesting @Override public void onConfigurationChanged(Configuration newConfig, int newDisplayId) { final Context context = mContextRef.get(); diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java index a5a98a98f0be..109b7ab73d6f 100644 --- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java @@ -17,6 +17,8 @@ package android.service.notification; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertFalse; @@ -51,6 +53,7 @@ public class StatusBarNotificationTest { private final Context mMockContext = mock(Context.class); @Mock + private Context mRealContext; private PackageManager mPm; private static final String PKG = "com.example.o"; @@ -75,6 +78,8 @@ public class StatusBarNotificationTest { InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); + + mRealContext = InstrumentationRegistry.getContext(); } @Test @@ -199,6 +204,19 @@ public class StatusBarNotificationTest { } + @Test + public void testGetPackageContext_worksWithUserAll() { + String pkg = "com.android.systemui"; + int uid = 1000; + Notification notification = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID).build(); + StatusBarNotification sbn = new StatusBarNotification( + pkg, pkg, ID, TAG, uid, uid, notification, UserHandle.ALL, null, UID); + Context resultContext = sbn.getPackageContext(mRealContext); + assertNotNull(resultContext); + assertNotSame(mRealContext, resultContext); + assertEquals(pkg, resultContext.getPackageName()); + } + private StatusBarNotification getNotification(String pkg, String group, String channelId) { return getNotification(pkg, getNotificationBuilder(group, channelId)); } diff --git a/core/tests/coretests/src/android/window/WindowContextControllerTest.java b/core/tests/coretests/src/android/window/WindowContextControllerTest.java index 020f4a06b892..073e46827bbb 100644 --- a/core/tests/coretests/src/android/window/WindowContextControllerTest.java +++ b/core/tests/coretests/src/android/window/WindowContextControllerTest.java @@ -23,11 +23,13 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.content.res.Configuration; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.IWindowManager; @@ -38,6 +40,8 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; /** * Tests for {@link WindowContextController} @@ -53,15 +57,18 @@ import org.junit.runner.RunWith; @Presubmit public class WindowContextControllerTest { private WindowContextController mController; + @Mock private IWindowManager mMockWms; + @Mock + private WindowTokenClient mMockToken; @Before public void setUp() throws Exception { - mMockWms = mock(IWindowManager.class); - mController = new WindowContextController(new Binder(), mMockWms); - - doReturn(true).when(mMockWms).attachWindowContextToDisplayArea(any(), anyInt(), - anyInt(), any()); + MockitoAnnotations.initMocks(this); + mController = new WindowContextController(mMockToken, mMockWms); + doNothing().when(mMockToken).onConfigurationChanged(any(), anyInt()); + doReturn(new Configuration()).when(mMockWms).attachWindowContextToDisplayArea(any(), + anyInt(), anyInt(), any()); } @Test(expected = IllegalStateException.class) @@ -85,6 +92,7 @@ public class WindowContextControllerTest { null /* options */); assertThat(mController.mAttachedToDisplayArea).isTrue(); + verify(mMockToken).onConfigurationChanged(any(), eq(DEFAULT_DISPLAY)); mController.detachIfNeeded(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index ba0ab6db1003..656bdff0c782 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -336,6 +336,13 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } @Override + public void onImeDrawnOnTask(int taskId) { + if (mStartingWindow != null) { + mStartingWindow.onImeDrawnOnTask(taskId); + } + } + + @Override public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { synchronized (mLock) { onTaskAppeared(new TaskAppearedInfo(taskInfo, leash)); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index fc7c86d669cb..147f5e30f9d6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -545,6 +545,15 @@ public class StartingSurfaceDrawer { removeWindowSynced(taskId, null, null, false); } + void onImeDrawnOnTask(int taskId) { + final StartingWindowRecord record = mStartingWindowRecords.get(taskId); + if (record != null && record.mTaskSnapshotWindow != null + && record.mTaskSnapshotWindow.hasImeSurface()) { + record.mTaskSnapshotWindow.removeImmediately(); + } + mStartingWindowRecords.remove(taskId); + } + protected void removeWindowSynced(int taskId, SurfaceControl leash, Rect frame, boolean playRevealAnimation) { final StartingWindowRecord record = mStartingWindowRecords.get(taskId); @@ -572,14 +581,15 @@ public class StartingSurfaceDrawer { Slog.e(TAG, "Found empty splash screen, remove!"); removeWindowInner(record.mDecorView, false); } + mStartingWindowRecords.remove(taskId); } if (record.mTaskSnapshotWindow != null) { if (DEBUG_TASK_SNAPSHOT) { Slog.v(TAG, "Removing task snapshot window for " + taskId); } - record.mTaskSnapshotWindow.remove(); + record.mTaskSnapshotWindow.scheduleRemove( + () -> mStartingWindowRecords.remove(taskId)); } - mStartingWindowRecords.remove(taskId); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index e84d498a9258..dee21b093dce 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -177,6 +177,13 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo } /** + * Called when the IME has drawn on the organized task. + */ + public void onImeDrawnOnTask(int taskId) { + mSplashScreenExecutor.execute(() -> mStartingSurfaceDrawer.onImeDrawnOnTask(taskId)); + } + + /** * Called when the content of a task is ready to show, starting window can be removed. */ public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index 6052d3dee891..72295148f678 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -16,7 +16,6 @@ package com.android.wm.shell.startingsurface; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.graphics.Color.WHITE; import static android.graphics.Color.alpha; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; @@ -64,7 +63,6 @@ import android.graphics.RectF; import android.hardware.HardwareBuffer; import android.os.IBinder; import android.os.RemoteException; -import android.os.SystemClock; import android.os.Trace; import android.util.MergedConfiguration; import android.util.Slog; @@ -119,7 +117,12 @@ public class TaskSnapshotWindow { private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s"; private static final long DELAY_REMOVAL_TIME_GENERAL = 100; - private static final long DELAY_REMOVAL_TIME_IME_VISIBLE = 350; + /** + * The max delay time in milliseconds for removing the task snapshot window with IME visible. + * Ideally the delay time will be shorter when receiving + * {@link StartingSurfaceDrawer#onImeDrawnOnTask(int)}. + */ + private static final long MAX_DELAY_REMOVAL_TIME_IME_VISIBLE = 450; //tmp vars for unused relayout params private static final Point TMP_SURFACE_SIZE = new Point(); @@ -138,7 +141,6 @@ public class TaskSnapshotWindow { private final RectF mTmpDstFrame = new RectF(); private final CharSequence mTitle; private boolean mHasDrawn; - private long mShownTime; private boolean mSizeMismatch; private final Paint mBackgroundPaint = new Paint(); private final int mActivityType; @@ -148,6 +150,8 @@ public class TaskSnapshotWindow { private final SurfaceControl.Transaction mTransaction; private final Matrix mSnapshotMatrix = new Matrix(); private final float[] mTmpFloat9 = new float[9]; + private Runnable mScheduledRunnable; + private final boolean mHasImeSurface; static TaskSnapshotWindow create(StartingWindowInfo info, IBinder appToken, TaskSnapshot snapshot, ShellExecutor splashScreenExecutor, @@ -216,7 +220,7 @@ public class TaskSnapshotWindow { taskDescription.setBackgroundColor(WHITE); } - final long delayRemovalTime = snapshot.hasImeSurface() ? DELAY_REMOVAL_TIME_IME_VISIBLE + final long delayRemovalTime = snapshot.hasImeSurface() ? MAX_DELAY_REMOVAL_TIME_IME_VISIBLE : DELAY_REMOVAL_TIME_GENERAL; final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow( @@ -281,12 +285,17 @@ public class TaskSnapshotWindow { mDelayRemovalTime = delayRemovalTime; mTransaction = new SurfaceControl.Transaction(); mClearWindowHandler = clearWindowHandler; + mHasImeSurface = snapshot.hasImeSurface(); } int getBackgroundColor() { return mBackgroundPaint.getColor(); } + boolean hasImeSurface() { + return mHasImeSurface; + } + /** * Ask system bar background painter to draw status bar background. * @hide @@ -304,21 +313,26 @@ public class TaskSnapshotWindow { mSystemBarBackgroundPainter.drawNavigationBarBackground(c); } - void remove() { - final long now = SystemClock.uptimeMillis(); - if ((now - mShownTime < mDelayRemovalTime) - // Show the latest content as soon as possible for unlocking to home. - && mActivityType != ACTIVITY_TYPE_HOME) { - final long delayTime = mShownTime + mDelayRemovalTime - now; - mSplashScreenExecutor.executeDelayed(() -> remove(), delayTime); - if (DEBUG) { - Slog.d(TAG, "Defer removing snapshot surface in " + delayTime); - } - return; + void scheduleRemove(Runnable onRemove) { + if (mScheduledRunnable != null) { + mSplashScreenExecutor.removeCallbacks(mScheduledRunnable); + mScheduledRunnable = null; + } + mScheduledRunnable = () -> { + TaskSnapshotWindow.this.removeImmediately(); + onRemove.run(); + }; + mSplashScreenExecutor.executeDelayed(mScheduledRunnable, mDelayRemovalTime); + if (DEBUG) { + Slog.d(TAG, "Defer removing snapshot surface in " + mDelayRemovalTime); } + } + + void removeImmediately() { + mSplashScreenExecutor.removeCallbacks(mScheduledRunnable); try { if (DEBUG) { - Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn); + Slog.d(TAG, "Removing taskSnapshot surface, mHasDrawn: " + mHasDrawn); } mSession.remove(mWindow); } catch (RemoteException e) { @@ -356,7 +370,6 @@ public class TaskSnapshotWindow { } else { drawSizeMatchSnapshot(); } - mShownTime = SystemClock.uptimeMillis(); mHasDrawn = true; reportDrawn(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index d536adb9f8ae..eef0d9bb268f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -15,38 +15,53 @@ */ package com.android.wm.shell.startingsurface; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.graphics.ColorSpace; +import android.graphics.Point; import android.graphics.Rect; +import android.hardware.HardwareBuffer; import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.UserHandle; import android.testing.TestableContext; +import android.view.IWindowSession; +import android.view.InsetsState; +import android.view.Surface; import android.view.SurfaceControl; import android.view.View; import android.view.WindowManager; +import android.view.WindowManagerGlobal; import android.view.WindowMetrics; import android.window.StartingWindowInfo; +import android.window.TaskSnapshot; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -61,6 +76,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; import java.util.function.IntSupplier; @@ -78,6 +94,7 @@ public class StartingSurfaceDrawerTests { private TransactionPool mTransactionPool; private final Handler mTestHandler = new Handler(Looper.getMainLooper()); + private ShellExecutor mTestExecutor; private final TestableContext mTestContext = new TestContext( InstrumentationRegistry.getInstrumentation().getTargetContext()); TestStartingSurfaceDrawer mStartingSurfaceDrawer; @@ -138,9 +155,9 @@ public class StartingSurfaceDrawerTests { doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics(); doNothing().when(mMockWindowManager).addView(any(), any()); - - mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(mTestContext, - new HandlerExecutor(mTestHandler), mTransactionPool)); + mTestExecutor = new HandlerExecutor(mTestHandler); + mStartingSurfaceDrawer = spy( + new TestStartingSurfaceDrawer(mTestContext, mTestExecutor, mTransactionPool)); } @Test @@ -205,6 +222,48 @@ public class StartingSurfaceDrawerTests { assertEquals(0, windowColor3.mReuseCount); } + @Test + public void testRemoveTaskSnapshotWithImeSurfaceWhenOnImeDrawn() throws Exception { + final int taskId = 1; + final StartingWindowInfo windowInfo = + createWindowInfo(taskId, android.R.style.Theme); + TaskSnapshot snapshot = createTaskSnapshot(100, 100, new Point(100, 100), + new Rect(0, 0, 0, 50), true /* hasImeSurface */); + final IWindowSession session = WindowManagerGlobal.getWindowSession(); + spyOn(session); + doReturn(WindowManagerGlobal.ADD_OKAY).when(session).addToDisplay( + any() /* window */, any() /* attrs */, + anyInt() /* viewVisibility */, anyInt() /* displayId */, + any() /* requestedVisibility */, any() /* outInputChannel */, + any() /* outInsetsState */, any() /* outActiveControls */); + TaskSnapshotWindow mockSnapshotWindow = TaskSnapshotWindow.create(windowInfo, + mBinder, + snapshot, mTestExecutor, () -> { + }); + spyOn(mockSnapshotWindow); + try (AutoCloseable mockTaskSnapshotSession = new AutoCloseable() { + MockitoSession mockSession = mockitoSession() + .initMocks(this) + .mockStatic(TaskSnapshotWindow.class) + .startMocking(); + @Override + public void close() { + mockSession.finishMocking(); + } + }) { + when(TaskSnapshotWindow.create(eq(windowInfo), eq(mBinder), eq(snapshot), any(), + any())).thenReturn(mockSnapshotWindow); + // Simulate a task snapshot window created with IME snapshot shown. + mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, mBinder, snapshot); + waitHandlerIdle(mTestHandler); + + // Verify the task snapshot with IME snapshot will be removed when received the real IME + // drawn callback. + mStartingSurfaceDrawer.onImeDrawnOnTask(1); + verify(mockSnapshotWindow).removeImmediately(); + } + } + private StartingWindowInfo createWindowInfo(int taskId, int themeResId) { StartingWindowInfo windowInfo = new StartingWindowInfo(); final ActivityInfo info = new ActivityInfo(); @@ -216,10 +275,27 @@ public class StartingSurfaceDrawerTests { taskInfo.taskId = taskId; windowInfo.targetActivityInfo = info; windowInfo.taskInfo = taskInfo; + windowInfo.topOpaqueWindowInsetsState = new InsetsState(); + windowInfo.mainWindowLayoutParams = new WindowManager.LayoutParams(); + windowInfo.topOpaqueWindowLayoutParams = new WindowManager.LayoutParams(); return windowInfo; } private static void waitHandlerIdle(Handler handler) { handler.runWithScissors(() -> { }, 0 /* timeout */); } + + private TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize, + Rect contentInsets, boolean hasImeSurface) { + final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888, + 1, HardwareBuffer.USAGE_CPU_READ_RARELY); + return new TaskSnapshot( + System.currentTimeMillis(), + new ComponentName("", ""), buffer, + ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, + Surface.ROTATION_0, taskSize, contentInsets, false, + true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, + 0 /* systemUiVisibility */, false /* isTranslucent */, + hasImeSurface /* hasImeSurface */); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index 70f52ad5432d..50e7e43822ea 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -58,9 +58,11 @@ import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.DeviceInfoUtils; +import com.android.settingslib.SignalIcon; import com.android.settingslib.Utils; import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.mobile.MobileMappings; +import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.settingslib.wifi.WifiUtils; import com.android.systemui.R; @@ -534,6 +536,14 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, } int resId = mapIconSets(config).get(iconKey).dataContentDescription; + final MergedCarrierEntry mergedCarrierEntry = + mAccessPointController.getMergedCarrierEntry(); + if (mergedCarrierEntry != null && mergedCarrierEntry.isDefaultNetwork()) { + SignalIcon.MobileIconGroup carrierMergedWifiIconGroup = + TelephonyIcons.CARRIER_MERGED_WIFI; + resId = carrierMergedWifiIconGroup.dataContentDescription; + } + return resId != 0 ? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) : ""; } diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index f32aa2295cb8..9da6d528a967 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -157,6 +157,9 @@ public final class CachedAppOptimizer { static final int SYNC_RECEIVED_WHILE_FROZEN = 1; static final int ASYNC_RECEIVED_WHILE_FROZEN = 2; + // Bitfield values for sync transactions received by frozen binder threads + static final int TXNS_PENDING_WHILE_FROZEN = 4; + /** * This thread must be moved to the system background cpuset. * If that doesn't happen, it's probably going to draw a lot of power. @@ -611,8 +614,9 @@ public final class CachedAppOptimizer { * binder for the specificed pid. * * @throws RuntimeException in case a flush/freeze operation could not complete successfully. + * @return 0 if success, or -EAGAIN indicating there's pending transaction. */ - private static native void freezeBinder(int pid, boolean freeze); + private static native int freezeBinder(int pid, boolean freeze); /** * Retrieves binder freeze info about a process. @@ -948,7 +952,7 @@ public final class CachedAppOptimizer { int freezeInfo = getBinderFreezeInfo(pid); if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) { - Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " " + Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " received sync transactions while frozen, killing"); app.killLocked("Sync transaction while in frozen state", ApplicationExitInfo.REASON_OTHER, @@ -956,8 +960,8 @@ public final class CachedAppOptimizer { processKilled = true; } - if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0) { - Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " " + if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0 && DEBUG_FREEZER) { + Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " received async transactions while frozen"); } } catch (Exception e) { @@ -1292,7 +1296,9 @@ public final class CachedAppOptimizer { public void handleMessage(Message msg) { switch (msg.what) { case SET_FROZEN_PROCESS_MSG: - freezeProcess((ProcessRecord) msg.obj); + synchronized (mAm) { + freezeProcess((ProcessRecord) msg.obj); + } break; case REPORT_UNFREEZE_MSG: int pid = msg.arg1; @@ -1306,6 +1312,15 @@ public final class CachedAppOptimizer { } } + @GuardedBy({"mAm", "mProcLock"}) + private void rescheduleFreeze(final ProcessRecord proc, final String reason) { + Slog.d(TAG_AM, "Reschedule freeze for process " + proc.getPid() + + " " + proc.processName + " (" + reason + ")"); + unfreezeAppLSP(proc); + freezeAppAsyncLSP(proc); + } + + @GuardedBy({"mAm"}) private void freezeProcess(final ProcessRecord proc) { int pid = proc.getPid(); // Unlocked intentionally final String name = proc.processName; @@ -1355,10 +1370,15 @@ public final class CachedAppOptimizer { return; } + Slog.d(TAG_AM, "freezing " + pid + " " + name); + // Freeze binder interface before the process, to flush any // transactions that might be pending. try { - freezeBinder(pid, true); + if (freezeBinder(pid, true) != 0) { + rescheduleFreeze(proc, "outstanding txns"); + return; + } } catch (RuntimeException e) { Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); mFreezeHandler.post(() -> { @@ -1404,24 +1424,36 @@ public final class CachedAppOptimizer { try { // post-check to prevent races + int freezeInfo = getBinderFreezeInfo(pid); + + if ((freezeInfo & TXNS_PENDING_WHILE_FROZEN) != 0) { + synchronized (mProcLock) { + rescheduleFreeze(proc, "new pending txns"); + } + return; + } + } catch (RuntimeException e) { + Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); + mFreezeHandler.post(() -> { + synchronized (mAm) { + proc.killLocked("Unable to freeze binder interface", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true); + } + }); + } + + try { + // post-check to prevent races if (mProcLocksReader.hasFileLocks(pid)) { if (DEBUG_FREEZER) { Slog.d(TAG_AM, name + " (" + pid + ") holds file locks, reverting freeze"); } - - synchronized (mAm) { - synchronized (mProcLock) { - unfreezeAppLSP(proc); - } - } + unfreezeAppLSP(proc); } } catch (Exception e) { Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e); - synchronized (mAm) { - synchronized (mProcLock) { - unfreezeAppLSP(proc); - } - } + unfreezeAppLSP(proc); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index d13c8ba96d48..0afc76d2ca30 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2253,6 +2253,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } + void removeStartingWindowIfNeeded() { + // Removing the task snapshot after the task is actually focused (see + // Task#onWindowFocusChanged). Since some of the app contents may draw in this time and + // requires more times to draw finish, in case flicking may happen when removing the task + // snapshot too early. (i.e. Showing IME.) + if ((mStartingData instanceof SnapshotStartingData) && !getTask().isFocused()) { + return; + } + removeStartingWindow(); + } + void removeStartingWindow() { removeStartingWindowAnimation(true /* prepareAnimation */); } @@ -5824,7 +5835,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // own stuff. win.cancelAnimation(); } - removeStartingWindow(); + removeStartingWindowIfNeeded(); updateReportedVisibilityLocked(); } diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 18ea738b08ce..aa257f847e25 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -464,7 +464,8 @@ class DragState { if (mDragInProgress && isValidDropTarget(newWin, containsAppExtras, interceptsGlobalDrag)) { // Only allow the extras to be dispatched to a global-intercepting drag target ClipData data = interceptsGlobalDrag ? mData.copyForTransferWithActivityInfo() : null; - DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY, + DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, + newWin.translateToWindowX(touchX), newWin.translateToWindowY(touchY), data, false /* includeDragSurface */, null /* dragAndDropPermission */); try { diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index da47328691c0..ed1e784bf275 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -90,6 +90,24 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { onSourceChanged(); } + @Override + protected boolean updateClientVisibility(InsetsControlTarget caller) { + boolean changed = super.updateClientVisibility(caller); + if (changed && caller.getRequestedVisibility(mSource.getType())) { + reportImeDrawnForOrganizer(caller); + } + return changed; + } + + private void reportImeDrawnForOrganizer(InsetsControlTarget caller) { + if (caller.getWindow() != null && caller.getWindow().getTask() != null) { + if (caller.getWindow().getTask().isOrganized()) { + mWin.mWmService.mAtmService.mTaskOrganizerController.reportImeDrawnOnTask( + caller.getWindow().getTask()); + } + } + } + private void onSourceChanged() { if (mLastSource.equals(mSource)) { return; diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index fe1020c86041..cf0f973fa7db 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -106,13 +106,13 @@ class KeyguardController { } /** - * @return {@code true} for default display when AOD is showing. Otherwise, same as - * {@link #isKeyguardOrAodShowing(int)} + * @return {@code true} for default display when AOD is showing, not going away. Otherwise, same + * as {@link #isKeyguardOrAodShowing(int)} * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic. */ boolean isKeyguardUnoccludedOrAodShowing(int displayId) { if (displayId == DEFAULT_DISPLAY && mAodShowing) { - return true; + return !mKeyguardGoingAway; } return isKeyguardOrAodShowing(displayId); } @@ -477,7 +477,7 @@ class KeyguardController { final KeyguardDisplayState state = getDisplayState(displayId); if (isKeyguardUnoccludedOrAodShowing(displayId)) { state.mSleepTokenAcquirer.acquire(displayId); - } else if (!isKeyguardUnoccludedOrAodShowing(displayId)) { + } else { state.mSleepTokenAcquirer.release(displayId); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index ced5af126e49..364594e4286a 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -5144,7 +5144,7 @@ class Task extends WindowContainer<WindowContainer> { /** * @return true if the task is currently focused. */ - private boolean isFocused() { + boolean isFocused() { if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) { return false; } @@ -5206,6 +5206,10 @@ class Task extends WindowContainer<WindowContainer> { * @param hasFocus */ void onWindowFocusChanged(boolean hasFocus) { + final ActivityRecord topAct = getTopVisibleActivity(); + if (topAct != null && (topAct.mStartingData instanceof SnapshotStartingData)) { + topAct.removeStartingWindowIfNeeded(); + } updateShadowsRadius(hasFocus, getSyncTransaction()); // TODO(b/180525887): Un-comment once there is resolution on the bug. // dispatchTaskInfoChangedIfNeeded(false /* force */); diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 09c5581385dd..88467baa6c34 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -733,6 +733,17 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { mPendingTaskEvents.clear(); } + void reportImeDrawnOnTask(Task task) { + final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder()); + if (state != null) { + try { + state.mOrganizer.mTaskOrganizer.onImeDrawnOnTask(task.mTaskId); + } catch (RemoteException e) { + Slog.e(TAG, "Exception sending onImeDrawnOnTask callback", e); + } + } + } + void onTaskInfoChanged(Task task, boolean force) { if (!task.mTaskAppearedSent) { // Skip if task still not appeared. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 2913e1071ed6..e3b25a5fda3e 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2717,8 +2717,8 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public boolean attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId, - Bundle options) { + public Configuration attachWindowContextToDisplayArea(IBinder clientToken, int + type, int displayId, Bundle options) { final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS, "attachWindowContextToDisplayArea", false /* printLog */); final int callingUid = Binder.getCallingUid(); @@ -2729,15 +2729,17 @@ public class WindowManagerService extends IWindowManager.Stub if (dc == null) { ProtoLog.w(WM_ERROR, "attachWindowContextToDisplayArea: trying to attach" + " to a non-existing display:%d", displayId); - return false; + return null; } // TODO(b/155340867): Investigate if we still need roundedCornerOverlay after // the feature b/155340867 is completed. final DisplayArea da = dc.findAreaForWindowType(type, options, callerCanManageAppTokens, false /* roundedCornerOverlay */); + // TODO(b/190019118): Avoid to send onConfigurationChanged because it has been done + // in return value of attachWindowContextToDisplayArea. mWindowContextListenerController.registerWindowContainerListener(clientToken, da, callingUid, type, options); - return true; + return da.getConfiguration(); } } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp index e319e3febc21..4190a91710fc 100644 --- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp +++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp @@ -55,6 +55,7 @@ using android::base::unique_fd; #define SYNC_RECEIVED_WHILE_FROZEN (1) #define ASYNC_RECEIVED_WHILE_FROZEN (2) +#define TXNS_PENDING_WHILE_FROZEN (4) namespace android { @@ -232,17 +233,20 @@ static void com_android_server_am_CachedAppOptimizer_compactProcess(JNIEnv*, job compactProcessOrFallback(pid, compactionFlags); } -static void com_android_server_am_CachedAppOptimizer_freezeBinder( +static jint com_android_server_am_CachedAppOptimizer_freezeBinder( JNIEnv *env, jobject clazz, jint pid, jboolean freeze) { - if (IPCThreadState::freeze(pid, freeze, 100 /* timeout [ms] */) != 0) { + jint retVal = IPCThreadState::freeze(pid, freeze, 100 /* timeout [ms] */); + if (retVal != 0 && retVal != -EAGAIN) { jniThrowException(env, "java/lang/RuntimeException", "Unable to freeze/unfreeze binder"); } + + return retVal; } static jint com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo(JNIEnv *env, jobject clazz, jint pid) { - bool syncReceived = false, asyncReceived = false; + uint32_t syncReceived = 0, asyncReceived = 0; int error = IPCThreadState::getProcessFreezeInfo(pid, &syncReceived, &asyncReceived); @@ -252,13 +256,12 @@ static jint com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo(JNIEnv jint retVal = 0; - if(syncReceived) { - retVal |= SYNC_RECEIVED_WHILE_FROZEN;; - } - - if(asyncReceived) { - retVal |= ASYNC_RECEIVED_WHILE_FROZEN; - } + // bit 0 of sync_recv goes to bit 0 of retVal + retVal |= syncReceived & SYNC_RECEIVED_WHILE_FROZEN; + // bit 0 of async_recv goes to bit 1 of retVal + retVal |= (asyncReceived << 1) & ASYNC_RECEIVED_WHILE_FROZEN; + // bit 1 of sync_recv goes to bit 2 of retVal + retVal |= (syncReceived << 1) & TXNS_PENDING_WHILE_FROZEN; return retVal; } @@ -278,7 +281,7 @@ static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem}, {"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess}, - {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder}, + {"freezeBinder", "(IZ)I", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder}, {"getBinderFreezeInfo", "(I)I", (void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo}, {"getFreezerCheckPath", "()Ljava/lang/String;", diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 91d4f7e2a24d..33e32393090e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -435,7 +435,6 @@ public final class SystemServer implements Dumpable { private static final String SYSPROP_START_UPTIME = "sys.system_server.start_uptime"; private Future<?> mZygotePreload; - private Future<?> mBlobStoreServiceStart; private final SystemServerDumper mDumper = new SystemServerDumper(); @@ -2250,12 +2249,9 @@ public final class SystemServer implements Dumpable { t.traceEnd(); } - mBlobStoreServiceStart = SystemServerInitThreadPool.submit(() -> { - final TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog(); - traceLog.traceBegin(START_BLOB_STORE_SERVICE); - mSystemServiceManager.startService(BLOB_STORE_MANAGER_SERVICE_CLASS); - traceLog.traceEnd(); - }, START_BLOB_STORE_SERVICE); + t.traceBegin(START_BLOB_STORE_SERVICE); + mSystemServiceManager.startService(BLOB_STORE_MANAGER_SERVICE_CLASS); + t.traceEnd(); // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode) t.traceBegin("StartDreamManager"); @@ -2650,9 +2646,6 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(MEDIA_COMMUNICATION_SERVICE_CLASS); t.traceEnd(); - ConcurrentUtils.waitForFutureNoInterrupt(mBlobStoreServiceStart, - START_BLOB_STORE_SERVICE); - // These are needed to propagate to the runnable below. final NetworkManagementService networkManagementF = networkManagement; final NetworkStatsService networkStatsF = networkStats; diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 12fc2f4ea1f4..5a6581f94154 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -2166,6 +2166,21 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testKeyguardGoingAwayWhileAodShown() { + mDisplayContent.getDisplayPolicy().setAwake(true); + + final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin"); + final ActivityRecord activity = appWin.mActivityRecord; + + mAtm.mKeyguardController.setKeyguardShown(true /* keyguardShowing */, + true /* aodShowing */); + assertFalse(activity.isVisibleRequested()); + + mAtm.mKeyguardController.keyguardGoingAway(0 /* flags */); + assertTrue(activity.isVisibleRequested()); + } + + @Test public void testRemoveRootTaskInWindowingModes() { removeRootTaskTests(() -> mRootWindowContainer.removeRootTasksInWindowingModes( WINDOWING_MODE_FULLSCREEN)); diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java index f2418c68358d..a8ede13e5de6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java @@ -82,7 +82,7 @@ public class InputMethodMenuControllerTest extends WindowTestsBase { mWm.mWindowContextListenerController.registerWindowContainerListener(clientToken, dc.getImeContainer(), 1000 /* ownerUid */, TYPE_INPUT_METHOD_DIALOG, null /* options */); - return true; + return dc.getImeContainer().getConfiguration(); }).when(wms).attachWindowContextToDisplayArea(any(), eq(TYPE_INPUT_METHOD_DIALOG), anyInt(), any()); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index d6a8401f5b18..ab496cf34acc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -797,6 +797,9 @@ public class WindowOrganizerTests extends WindowTestsBase { public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { } @Override + public void onImeDrawnOnTask(int taskId) throws RemoteException { + } + @Override public void onAppSplashScreenViewRemoved(int taskId) { } }; diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index a9aeb985d115..4dc83ae98d89 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -269,13 +269,11 @@ final class HotwordDetectionConnection { Slog.v(TAG, "cancelLocked"); clearDebugHotwordLoggingTimeoutLocked(); mDebugHotwordLogging = false; - if (mRemoteHotwordDetectionService.isBound()) { - mRemoteHotwordDetectionService.unbind(); - LocalServices.getService(PermissionManagerServiceInternal.class) - .setHotwordDetectionServiceProvider(null); - mIdentity = null; - updateServiceUidForAudioPolicy(Process.INVALID_UID); - } + mRemoteHotwordDetectionService.unbind(); + LocalServices.getService(PermissionManagerServiceInternal.class) + .setHotwordDetectionServiceProvider(null); + mIdentity = null; + updateServiceUidForAudioPolicy(Process.INVALID_UID); mCancellationTaskFuture.cancel(/* may interrupt */ true); if (mAudioFlinger != null) { mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0); |