Loading services/core/java/com/android/server/wm/ClientLifecycleManager.java +19 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,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. Loading @@ -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); Loading @@ -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); Loading services/core/java/com/android/server/wm/WindowProcessController.java +16 −8 Original line number Diff line number Diff line Loading @@ -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); } } } Loading Loading @@ -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) { Loading @@ -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 Loading services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java +5 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading
services/core/java/com/android/server/wm/ClientLifecycleManager.java +19 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,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. Loading @@ -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); Loading @@ -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); Loading
services/core/java/com/android/server/wm/WindowProcessController.java +16 −8 Original line number Diff line number Diff line Loading @@ -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); } } } Loading Loading @@ -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) { Loading @@ -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 Loading
services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java +5 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading