diff options
3 files changed, 40 insertions, 14 deletions
diff --git a/services/core/java/com/android/server/wm/ClientLifecycleManager.java b/services/core/java/com/android/server/wm/ClientLifecycleManager.java index 28f656e624fb..8b282dd3e7a8 100644 --- a/services/core/java/com/android/server/wm/ClientLifecycleManager.java +++ b/services/core/java/com/android/server/wm/ClientLifecycleManager.java @@ -58,6 +58,23 @@ class ClientLifecycleManager { } /** + * Similar to {@link #scheduleTransactionItem}, but is called without WM lock. + * + * @see WindowProcessController#setReportedProcState(int) + */ + void scheduleTransactionItemUnlocked(@NonNull IApplicationThread client, + @NonNull ClientTransactionItem transactionItem) throws RemoteException { + // Immediately dispatching to client, and must not access WMS. + final ClientTransaction clientTransaction = ClientTransaction.obtain(client); + if (transactionItem.isActivityLifecycleItem()) { + clientTransaction.setLifecycleStateRequest((ActivityLifecycleItem) transactionItem); + } else { + clientTransaction.addCallback(transactionItem); + } + scheduleTransaction(clientTransaction); + } + + /** * Schedules a single transaction item, either a callback or a lifecycle request, delivery to * client application. * @throws RemoteException @@ -65,6 +82,7 @@ class ClientLifecycleManager { */ void scheduleTransactionItem(@NonNull IApplicationThread client, @NonNull ClientTransactionItem transactionItem) throws RemoteException { + // TODO(b/260873529): queue the transaction items. final ClientTransaction clientTransaction = ClientTransaction.obtain(client); if (transactionItem.isActivityLifecycleItem()) { clientTransaction.setLifecycleStateRequest((ActivityLifecycleItem) transactionItem); @@ -82,6 +100,7 @@ class ClientLifecycleManager { void scheduleTransactionAndLifecycleItems(@NonNull IApplicationThread client, @NonNull ClientTransactionItem transactionItem, @NonNull ActivityLifecycleItem lifecycleItem) throws RemoteException { + // TODO(b/260873529): replace with #scheduleTransactionItem after launch for cleanup. final ClientTransaction clientTransaction = ClientTransaction.obtain(client); clientTransaction.addCallback(transactionItem); clientTransaction.setLifecycleStateRequest(lifecycleItem); diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 558bf9d6310a..2b18f0775047 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -388,13 +388,22 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio final IApplicationThread thread = mThread; if (prevProcState >= CACHED_CONFIG_PROC_STATE && repProcState < CACHED_CONFIG_PROC_STATE && thread != null && mHasCachedConfiguration) { - final Configuration config; + final ConfigurationChangeItem configurationChangeItem; synchronized (mLastReportedConfiguration) { - config = new Configuration(mLastReportedConfiguration); + onConfigurationChangePreScheduled(mLastReportedConfiguration); + configurationChangeItem = ConfigurationChangeItem.obtain( + mLastReportedConfiguration, mLastTopActivityDeviceId); } // Schedule immediately to make sure the app component (e.g. receiver, service) can get // the latest configuration in their lifecycle callbacks (e.g. onReceive, onCreate). - scheduleConfigurationChange(thread, config); + try { + // No WM lock here. + mAtm.getLifecycleManager().scheduleTransactionItemUnlocked( + thread, configurationChangeItem); + } catch (Exception e) { + Slog.e(TAG_CONFIGURATION, "Failed to schedule ConfigurationChangeItem=" + + configurationChangeItem + " owner=" + mOwner, e); + } } } @@ -1634,11 +1643,12 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio } } - scheduleConfigurationChange(thread, config); + onConfigurationChangePreScheduled(config); + scheduleClientTransactionItem(thread, ConfigurationChangeItem.obtain( + config, mLastTopActivityDeviceId)); } - private void scheduleConfigurationChange(@NonNull IApplicationThread thread, - @NonNull Configuration config) { + private void onConfigurationChangePreScheduled(@NonNull Configuration config) { ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName, config); if (Build.IS_DEBUGGABLE && mHasImeService) { @@ -1646,8 +1656,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config); } mHasCachedConfiguration = false; - scheduleClientTransactionItem(thread, ConfigurationChangeItem.obtain( - config, mLastTopActivityDeviceId)); } @VisibleForTesting diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java index e152feb141e1..e31ee1174656 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java @@ -306,7 +306,7 @@ public class WindowProcessControllerTests extends WindowTestsBase { @Test public void testCachedStateConfigurationChange() throws RemoteException { - doNothing().when(mClientLifecycleManager).scheduleTransactionItem(any(), any()); + doNothing().when(mClientLifecycleManager).scheduleTransactionItemUnlocked(any(), any()); final IApplicationThread thread = mWpc.getThread(); final Configuration newConfig = new Configuration(mWpc.getConfiguration()); newConfig.densityDpi += 100; @@ -322,18 +322,17 @@ public class WindowProcessControllerTests extends WindowTestsBase { newConfig.densityDpi += 100; mWpc.onConfigurationChanged(newConfig); verify(mClientLifecycleManager, never()).scheduleTransactionItem(eq(thread), any()); + verify(mClientLifecycleManager, never()).scheduleTransactionItemUnlocked(eq(thread), any()); // Cached -> non-cached will send the previous deferred config immediately. mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_RECEIVER); final ArgumentCaptor<ConfigurationChangeItem> captor = ArgumentCaptor.forClass(ConfigurationChangeItem.class); - verify(mClientLifecycleManager).scheduleTransactionItem(eq(thread), captor.capture()); + verify(mClientLifecycleManager).scheduleTransactionItemUnlocked( + eq(thread), captor.capture()); final ClientTransactionHandler client = mock(ClientTransactionHandler.class); captor.getValue().preExecute(client); - final ArgumentCaptor<Configuration> configCaptor = - ArgumentCaptor.forClass(Configuration.class); - verify(client).updatePendingConfiguration(configCaptor.capture()); - assertEquals(newConfig, configCaptor.getValue()); + verify(client).updatePendingConfiguration(newConfig); } @Test |