Loading apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +8 −6 Original line number Original line Diff line number Diff line Loading @@ -127,6 +127,7 @@ public class UserLifecycleTests { private BroadcastWaiter mBroadcastWaiter; private BroadcastWaiter mBroadcastWaiter; private UserSwitchWaiter mUserSwitchWaiter; private UserSwitchWaiter mUserSwitchWaiter; private String mUserSwitchTimeoutMs; private String mUserSwitchTimeoutMs; private String mDisableUserSwitchingDialogAnimations; private final BenchmarkRunner mRunner = new BenchmarkRunner(); private final BenchmarkRunner mRunner = new BenchmarkRunner(); @Rule @Rule Loading @@ -153,16 +154,17 @@ public class UserLifecycleTests { Log.w(TAG, "WARNING: Tests are being run from user " + mAm.getCurrentUser() Log.w(TAG, "WARNING: Tests are being run from user " + mAm.getCurrentUser() + " rather than the system user"); + " rather than the system user"); } } mUserSwitchTimeoutMs = setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs = setSystemProperty( "100000"); "debug.usercontroller.user_switch_timeout_ms", "100000"); if (TextUtils.isEmpty(mUserSwitchTimeoutMs)) { mDisableUserSwitchingDialogAnimations = setSystemProperty( mUserSwitchTimeoutMs = "invalid"; "debug.usercontroller.disable_user_switching_dialog_animations", "true"); } } } @After @After public void tearDown() throws Exception { public void tearDown() throws Exception { setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs); setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs); setSystemProperty("debug.usercontroller.disable_user_switching_dialog_animations", mDisableUserSwitchingDialogAnimations); mBroadcastWaiter.close(); mBroadcastWaiter.close(); mUserSwitchWaiter.close(); mUserSwitchWaiter.close(); for (int userId : mUsersToRemove) { for (int userId : mUsersToRemove) { Loading Loading @@ -1538,7 +1540,7 @@ public class UserLifecycleTests { private String setSystemProperty(String name, String value) throws Exception { private String setSystemProperty(String name, String value) throws Exception { final String oldValue = ShellHelper.runShellCommand("getprop " + name); final String oldValue = ShellHelper.runShellCommand("getprop " + name); assertEquals("", ShellHelper.runShellCommand("setprop " + name + " " + value)); assertEquals("", ShellHelper.runShellCommand("setprop " + name + " " + value)); return oldValue; return TextUtils.firstNotEmpty(oldValue, "invalid"); } } private void waitForBroadcastIdle() { private void waitForBroadcastIdle() { Loading core/res/res/drawable/loading_spinner.xml 0 → 100644 +55 −0 Original line number Original line Diff line number Diff line <!-- Copyright (C) 2023 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:height="230dp" android:width="230dp" android:viewportHeight="230" android:viewportWidth="230"> <group android:name="_R_G"> <group android:name="_R_G_L_0_G" android:translateX="100.621" android:translateY="102.621"> <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="8" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M14.38 -93.62 C72.88,-93.62 120.38,-46.12 120.38,12.38 C120.38,70.88 72.88,118.38 14.38,118.38 C-44.12,118.38 -91.62,70.88 -91.62,12.38 C-91.62,-46.12 -44.12,-93.62 14.38,-93.62c "/> </group> </group> <group android:name="time_group"/> </vector> </aapt:attr> <target android:name="_R_G_L_0_G_D_0_P_0"> <aapt:attr name="android:animation"> <set android:ordering="together"> <objectAnimator android:propertyName="trimPathEnd" android:duration="350" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"> <aapt:attr name="android:interpolator"> <pathInterpolator android:pathData="M 0.0,0.0 c0.6,0 0.4,1 1.0,1.0"/> </aapt:attr> </objectAnimator> </set> </aapt:attr> </target> <target android:name="time_group"> <aapt:attr name="android:animation"> <set android:ordering="together"> <objectAnimator android:propertyName="translateX" android:duration="517" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> </set> </aapt:attr> </target> </animated-vector> No newline at end of file core/res/res/layout/user_switching_dialog.xml +42 −11 Original line number Original line Diff line number Diff line Loading @@ -14,17 +14,48 @@ See the License for the specific language governing permissions and See the License for the specific language governing permissions and limitations under the License. limitations under the License. --> --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:background="?attr/colorBackground" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:orientation="vertical" android:paddingBottom="77dp"> <RelativeLayout android:layout_width="242dp" android:layout_height="242dp" android:layout_gravity="center"> <ImageView android:id="@+id/icon" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="26dp" /> <ImageView android:id="@+id/progress_circular" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="6dp" android:src="@drawable/loading_spinner" /> </RelativeLayout> <TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/message" android:id="@+id/message" style="?attr/textAppearanceListItem" style="?attr/textAppearanceListItem" android:background="?attr/colorSurface" android:layout_width="wrap_content" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="20sp" android:drawablePadding="12dp" android:textAlignment="center" android:drawableTint="?attr/textColorPrimary" android:drawableTint="?attr/textColorPrimary" /> android:paddingStart="?attr/dialogPreferredPadding" android:paddingEnd="?attr/dialogPreferredPadding" </LinearLayout> android:paddingTop="24dp" </FrameLayout> android:paddingBottom="24dp" /> services/core/java/com/android/server/am/UserController.java +45 −52 Original line number Original line Diff line number Diff line Loading @@ -141,6 +141,7 @@ import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; /** /** * Helper class for {@link ActivityManagerService} responsible for multi-user functionality. * Helper class for {@link ActivityManagerService} responsible for multi-user functionality. Loading @@ -157,7 +158,7 @@ class UserController implements Handler.Callback { private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; // Amount of time we wait for observers to handle a user switch before // Amount of time we wait for observers to handle a user switch before // giving up on them and unfreezing the screen. // giving up on them and dismissing the user switching dialog. static final int DEFAULT_USER_SWITCH_TIMEOUT_MS = 3 * 1000; static final int DEFAULT_USER_SWITCH_TIMEOUT_MS = 3 * 1000; /** /** Loading Loading @@ -207,7 +208,7 @@ class UserController implements Handler.Callback { /** /** * Amount of time waited for {@link WindowManagerService#dismissKeyguard} callbacks to be * Amount of time waited for {@link WindowManagerService#dismissKeyguard} callbacks to be * called after dismissing the keyguard. * called after dismissing the keyguard. * Otherwise, we should move on to unfreeze the screen {@link #unfreezeScreen} * Otherwise, we should move on to dismiss the dialog {@link #dismissUserSwitchDialog()} * and report user switch is complete {@link #REPORT_USER_SWITCH_COMPLETE_MSG}. * and report user switch is complete {@link #REPORT_USER_SWITCH_COMPLETE_MSG}. */ */ private static final int DISMISS_KEYGUARD_TIMEOUT_MS = 2 * 1000; private static final int DISMISS_KEYGUARD_TIMEOUT_MS = 2 * 1000; Loading Loading @@ -1695,14 +1696,6 @@ class UserController implements Handler.Callback { return false; return false; } } if (foreground && isUserSwitchUiEnabled()) { t.traceBegin("startFreezingScreen"); mInjector.getWindowManager().startFreezingScreen( R.anim.screen_user_exit, R.anim.screen_user_enter); t.traceEnd(); } dismissUserSwitchDialog(); // so that we don't hold a reference to mUserSwitchingDialog boolean needStart = false; boolean needStart = false; boolean updateUmState = false; boolean updateUmState = false; UserState uss; UserState uss; Loading Loading @@ -1877,7 +1870,7 @@ class UserController implements Handler.Callback { if (!success) { if (!success) { mInjector.getWindowManager().setSwitchingUser(false); mInjector.getWindowManager().setSwitchingUser(false); mTargetUserId = UserHandle.USER_NULL; mTargetUserId = UserHandle.USER_NULL; dismissUserSwitchDialog(); dismissUserSwitchDialog(null); } } } } Loading Loading @@ -2015,22 +2008,26 @@ class UserController implements Handler.Callback { mUiHandler.sendMessage(mUiHandler.obtainMessage( mUiHandler.sendMessage(mUiHandler.obtainMessage( START_USER_SWITCH_UI_MSG, userNames)); START_USER_SWITCH_UI_MSG, userNames)); } else { } else { mHandler.removeMessages(START_USER_SWITCH_FG_MSG); sendStartUserSwitchFgMessage(targetUserId); mHandler.sendMessage(mHandler.obtainMessage( START_USER_SWITCH_FG_MSG, targetUserId, 0)); } } return true; return true; } } private void dismissUserSwitchDialog() { private void sendStartUserSwitchFgMessage(int targetUserId) { mInjector.dismissUserSwitchingDialog(); mHandler.removeMessages(START_USER_SWITCH_FG_MSG); mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_FG_MSG, targetUserId, 0)); } private void dismissUserSwitchDialog(Runnable onDismissed) { mInjector.dismissUserSwitchingDialog(onDismissed); } } private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { // The dialog will show and then initiate the user switch by calling startUserInForeground // The dialog will show and then initiate the user switch by calling startUserInForeground mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second, mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second, getSwitchingFromSystemUserMessageUnchecked(), getSwitchingFromSystemUserMessageUnchecked(), getSwitchingToSystemUserMessageUnchecked()); getSwitchingToSystemUserMessageUnchecked(), /* onShown= */ () -> sendStartUserSwitchFgMessage(fromToUserPair.second.id)); } } private void dispatchForegroundProfileChanged(@UserIdInt int userId) { private void dispatchForegroundProfileChanged(@UserIdInt int userId) { Loading Loading @@ -2236,7 +2233,7 @@ class UserController implements Handler.Callback { EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId); EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId); // Do the keyguard dismiss and unfreeze later // Do the keyguard dismiss and dismiss the user switching dialog later mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG); mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG); mHandler.sendMessage(mHandler.obtainMessage( mHandler.sendMessage(mHandler.obtainMessage( COMPLETE_USER_SWITCH_MSG, oldUserId, newUserId)); COMPLETE_USER_SWITCH_MSG, oldUserId, newUserId)); Loading @@ -2251,35 +2248,31 @@ class UserController implements Handler.Callback { @VisibleForTesting @VisibleForTesting void completeUserSwitch(int oldUserId, int newUserId) { void completeUserSwitch(int oldUserId, int newUserId) { final boolean isUserSwitchUiEnabled = isUserSwitchUiEnabled(); final boolean isUserSwitchUiEnabled = isUserSwitchUiEnabled(); final Runnable runnable = () -> { // serialize each conditional step if (isUserSwitchUiEnabled) { await( unfreezeScreen(); // STEP 1 - If there is no challenge set, dismiss the keyguard right away } isUserSwitchUiEnabled && !mInjector.getKeyguardManager().isDeviceSecure(newUserId), mInjector::dismissKeyguard, () -> await( // STEP 2 - If user switch ui was enabled, dismiss user switch dialog isUserSwitchUiEnabled, this::dismissUserSwitchDialog, () -> { // STEP 3 - Send REPORT_USER_SWITCH_COMPLETE_MSG to broadcast // ACTION_USER_SWITCHED & call UserSwitchObservers.onUserSwitchComplete mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG); mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG); mHandler.sendMessage(mHandler.obtainMessage( mHandler.sendMessage(mHandler.obtainMessage( REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId)); REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId)); }; // If there is no challenge set, dismiss the keyguard right away if (isUserSwitchUiEnabled && !mInjector.getKeyguardManager().isDeviceSecure(newUserId)) { // Wait until the keyguard is dismissed to unfreeze mInjector.dismissKeyguard(runnable); } else { runnable.run(); } } )); } } /** private void await(boolean condition, Consumer<Runnable> conditionalStep, Runnable nextStep) { * Tell WindowManager we're ready to unfreeze the screen, at its leisure. Note that there is if (condition) { * likely a lot going on, and WM won't unfreeze until the drawing is all done, so conditionalStep.accept(nextStep); * the actual unfreeze may still not happen for a long time; this is expected. } else { */ nextStep.run(); @VisibleForTesting } void unfreezeScreen() { TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("stopFreezingScreen"); mInjector.getWindowManager().stopFreezingScreen(); t.traceEnd(); } } private void moveUserToForeground(UserState uss, int newUserId) { private void moveUserToForeground(UserState uss, int newUserId) { Loading Loading @@ -3731,17 +3724,18 @@ class UserController implements Handler.Callback { mService.mCpHelper.installEncryptionUnawareProviders(userId); mService.mCpHelper.installEncryptionUnawareProviders(userId); } } void dismissUserSwitchingDialog() { void dismissUserSwitchingDialog(@Nullable Runnable onDismissed) { synchronized (mUserSwitchingDialogLock) { synchronized (mUserSwitchingDialogLock) { if (mUserSwitchingDialog != null) { if (mUserSwitchingDialog != null) { mUserSwitchingDialog.dismiss(); mUserSwitchingDialog.dismiss(onDismissed); mUserSwitchingDialog = null; mUserSwitchingDialog = null; } } } } } } void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, String switchingFromSystemUserMessage, String switchingToSystemUserMessage) { String switchingFromSystemUserMessage, String switchingToSystemUserMessage, @NonNull Runnable onShown) { if (mService.mContext.getPackageManager() if (mService.mContext.getPackageManager() .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { // config_customUserSwitchUi is set to true on Automotive as CarSystemUI is // config_customUserSwitchUi is set to true on Automotive as CarSystemUI is Loading @@ -3751,11 +3745,10 @@ class UserController implements Handler.Callback { + "condition if it's shown by CarSystemUI as well"); + "condition if it's shown by CarSystemUI as well"); } } synchronized (mUserSwitchingDialogLock) { synchronized (mUserSwitchingDialogLock) { dismissUserSwitchingDialog(); dismissUserSwitchingDialog(null); mUserSwitchingDialog = new UserSwitchingDialog(mService, mService.mContext, mUserSwitchingDialog = new UserSwitchingDialog(mService.mContext, fromUser, toUser, fromUser, toUser, true /* above system */, switchingFromSystemUserMessage, switchingFromSystemUserMessage, switchingToSystemUserMessage); switchingToSystemUserMessage); mUserSwitchingDialog.show(onShown); mUserSwitchingDialog.show(); } } } } Loading services/core/java/com/android/server/am/UserSwitchingDialog.java +201 −103 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +8 −6 Original line number Original line Diff line number Diff line Loading @@ -127,6 +127,7 @@ public class UserLifecycleTests { private BroadcastWaiter mBroadcastWaiter; private BroadcastWaiter mBroadcastWaiter; private UserSwitchWaiter mUserSwitchWaiter; private UserSwitchWaiter mUserSwitchWaiter; private String mUserSwitchTimeoutMs; private String mUserSwitchTimeoutMs; private String mDisableUserSwitchingDialogAnimations; private final BenchmarkRunner mRunner = new BenchmarkRunner(); private final BenchmarkRunner mRunner = new BenchmarkRunner(); @Rule @Rule Loading @@ -153,16 +154,17 @@ public class UserLifecycleTests { Log.w(TAG, "WARNING: Tests are being run from user " + mAm.getCurrentUser() Log.w(TAG, "WARNING: Tests are being run from user " + mAm.getCurrentUser() + " rather than the system user"); + " rather than the system user"); } } mUserSwitchTimeoutMs = setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs = setSystemProperty( "100000"); "debug.usercontroller.user_switch_timeout_ms", "100000"); if (TextUtils.isEmpty(mUserSwitchTimeoutMs)) { mDisableUserSwitchingDialogAnimations = setSystemProperty( mUserSwitchTimeoutMs = "invalid"; "debug.usercontroller.disable_user_switching_dialog_animations", "true"); } } } @After @After public void tearDown() throws Exception { public void tearDown() throws Exception { setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs); setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs); setSystemProperty("debug.usercontroller.disable_user_switching_dialog_animations", mDisableUserSwitchingDialogAnimations); mBroadcastWaiter.close(); mBroadcastWaiter.close(); mUserSwitchWaiter.close(); mUserSwitchWaiter.close(); for (int userId : mUsersToRemove) { for (int userId : mUsersToRemove) { Loading Loading @@ -1538,7 +1540,7 @@ public class UserLifecycleTests { private String setSystemProperty(String name, String value) throws Exception { private String setSystemProperty(String name, String value) throws Exception { final String oldValue = ShellHelper.runShellCommand("getprop " + name); final String oldValue = ShellHelper.runShellCommand("getprop " + name); assertEquals("", ShellHelper.runShellCommand("setprop " + name + " " + value)); assertEquals("", ShellHelper.runShellCommand("setprop " + name + " " + value)); return oldValue; return TextUtils.firstNotEmpty(oldValue, "invalid"); } } private void waitForBroadcastIdle() { private void waitForBroadcastIdle() { Loading
core/res/res/drawable/loading_spinner.xml 0 → 100644 +55 −0 Original line number Original line Diff line number Diff line <!-- Copyright (C) 2023 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:height="230dp" android:width="230dp" android:viewportHeight="230" android:viewportWidth="230"> <group android:name="_R_G"> <group android:name="_R_G_L_0_G" android:translateX="100.621" android:translateY="102.621"> <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="8" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M14.38 -93.62 C72.88,-93.62 120.38,-46.12 120.38,12.38 C120.38,70.88 72.88,118.38 14.38,118.38 C-44.12,118.38 -91.62,70.88 -91.62,12.38 C-91.62,-46.12 -44.12,-93.62 14.38,-93.62c "/> </group> </group> <group android:name="time_group"/> </vector> </aapt:attr> <target android:name="_R_G_L_0_G_D_0_P_0"> <aapt:attr name="android:animation"> <set android:ordering="together"> <objectAnimator android:propertyName="trimPathEnd" android:duration="350" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"> <aapt:attr name="android:interpolator"> <pathInterpolator android:pathData="M 0.0,0.0 c0.6,0 0.4,1 1.0,1.0"/> </aapt:attr> </objectAnimator> </set> </aapt:attr> </target> <target android:name="time_group"> <aapt:attr name="android:animation"> <set android:ordering="together"> <objectAnimator android:propertyName="translateX" android:duration="517" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/> </set> </aapt:attr> </target> </animated-vector> No newline at end of file
core/res/res/layout/user_switching_dialog.xml +42 −11 Original line number Original line Diff line number Diff line Loading @@ -14,17 +14,48 @@ See the License for the specific language governing permissions and See the License for the specific language governing permissions and limitations under the License. limitations under the License. --> --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:background="?attr/colorBackground" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:orientation="vertical" android:paddingBottom="77dp"> <RelativeLayout android:layout_width="242dp" android:layout_height="242dp" android:layout_gravity="center"> <ImageView android:id="@+id/icon" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="26dp" /> <ImageView android:id="@+id/progress_circular" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="6dp" android:src="@drawable/loading_spinner" /> </RelativeLayout> <TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/message" android:id="@+id/message" style="?attr/textAppearanceListItem" style="?attr/textAppearanceListItem" android:background="?attr/colorSurface" android:layout_width="wrap_content" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="20sp" android:drawablePadding="12dp" android:textAlignment="center" android:drawableTint="?attr/textColorPrimary" android:drawableTint="?attr/textColorPrimary" /> android:paddingStart="?attr/dialogPreferredPadding" android:paddingEnd="?attr/dialogPreferredPadding" </LinearLayout> android:paddingTop="24dp" </FrameLayout> android:paddingBottom="24dp" />
services/core/java/com/android/server/am/UserController.java +45 −52 Original line number Original line Diff line number Diff line Loading @@ -141,6 +141,7 @@ import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; /** /** * Helper class for {@link ActivityManagerService} responsible for multi-user functionality. * Helper class for {@link ActivityManagerService} responsible for multi-user functionality. Loading @@ -157,7 +158,7 @@ class UserController implements Handler.Callback { private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; // Amount of time we wait for observers to handle a user switch before // Amount of time we wait for observers to handle a user switch before // giving up on them and unfreezing the screen. // giving up on them and dismissing the user switching dialog. static final int DEFAULT_USER_SWITCH_TIMEOUT_MS = 3 * 1000; static final int DEFAULT_USER_SWITCH_TIMEOUT_MS = 3 * 1000; /** /** Loading Loading @@ -207,7 +208,7 @@ class UserController implements Handler.Callback { /** /** * Amount of time waited for {@link WindowManagerService#dismissKeyguard} callbacks to be * Amount of time waited for {@link WindowManagerService#dismissKeyguard} callbacks to be * called after dismissing the keyguard. * called after dismissing the keyguard. * Otherwise, we should move on to unfreeze the screen {@link #unfreezeScreen} * Otherwise, we should move on to dismiss the dialog {@link #dismissUserSwitchDialog()} * and report user switch is complete {@link #REPORT_USER_SWITCH_COMPLETE_MSG}. * and report user switch is complete {@link #REPORT_USER_SWITCH_COMPLETE_MSG}. */ */ private static final int DISMISS_KEYGUARD_TIMEOUT_MS = 2 * 1000; private static final int DISMISS_KEYGUARD_TIMEOUT_MS = 2 * 1000; Loading Loading @@ -1695,14 +1696,6 @@ class UserController implements Handler.Callback { return false; return false; } } if (foreground && isUserSwitchUiEnabled()) { t.traceBegin("startFreezingScreen"); mInjector.getWindowManager().startFreezingScreen( R.anim.screen_user_exit, R.anim.screen_user_enter); t.traceEnd(); } dismissUserSwitchDialog(); // so that we don't hold a reference to mUserSwitchingDialog boolean needStart = false; boolean needStart = false; boolean updateUmState = false; boolean updateUmState = false; UserState uss; UserState uss; Loading Loading @@ -1877,7 +1870,7 @@ class UserController implements Handler.Callback { if (!success) { if (!success) { mInjector.getWindowManager().setSwitchingUser(false); mInjector.getWindowManager().setSwitchingUser(false); mTargetUserId = UserHandle.USER_NULL; mTargetUserId = UserHandle.USER_NULL; dismissUserSwitchDialog(); dismissUserSwitchDialog(null); } } } } Loading Loading @@ -2015,22 +2008,26 @@ class UserController implements Handler.Callback { mUiHandler.sendMessage(mUiHandler.obtainMessage( mUiHandler.sendMessage(mUiHandler.obtainMessage( START_USER_SWITCH_UI_MSG, userNames)); START_USER_SWITCH_UI_MSG, userNames)); } else { } else { mHandler.removeMessages(START_USER_SWITCH_FG_MSG); sendStartUserSwitchFgMessage(targetUserId); mHandler.sendMessage(mHandler.obtainMessage( START_USER_SWITCH_FG_MSG, targetUserId, 0)); } } return true; return true; } } private void dismissUserSwitchDialog() { private void sendStartUserSwitchFgMessage(int targetUserId) { mInjector.dismissUserSwitchingDialog(); mHandler.removeMessages(START_USER_SWITCH_FG_MSG); mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_FG_MSG, targetUserId, 0)); } private void dismissUserSwitchDialog(Runnable onDismissed) { mInjector.dismissUserSwitchingDialog(onDismissed); } } private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { // The dialog will show and then initiate the user switch by calling startUserInForeground // The dialog will show and then initiate the user switch by calling startUserInForeground mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second, mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second, getSwitchingFromSystemUserMessageUnchecked(), getSwitchingFromSystemUserMessageUnchecked(), getSwitchingToSystemUserMessageUnchecked()); getSwitchingToSystemUserMessageUnchecked(), /* onShown= */ () -> sendStartUserSwitchFgMessage(fromToUserPair.second.id)); } } private void dispatchForegroundProfileChanged(@UserIdInt int userId) { private void dispatchForegroundProfileChanged(@UserIdInt int userId) { Loading Loading @@ -2236,7 +2233,7 @@ class UserController implements Handler.Callback { EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId); EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId); // Do the keyguard dismiss and unfreeze later // Do the keyguard dismiss and dismiss the user switching dialog later mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG); mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG); mHandler.sendMessage(mHandler.obtainMessage( mHandler.sendMessage(mHandler.obtainMessage( COMPLETE_USER_SWITCH_MSG, oldUserId, newUserId)); COMPLETE_USER_SWITCH_MSG, oldUserId, newUserId)); Loading @@ -2251,35 +2248,31 @@ class UserController implements Handler.Callback { @VisibleForTesting @VisibleForTesting void completeUserSwitch(int oldUserId, int newUserId) { void completeUserSwitch(int oldUserId, int newUserId) { final boolean isUserSwitchUiEnabled = isUserSwitchUiEnabled(); final boolean isUserSwitchUiEnabled = isUserSwitchUiEnabled(); final Runnable runnable = () -> { // serialize each conditional step if (isUserSwitchUiEnabled) { await( unfreezeScreen(); // STEP 1 - If there is no challenge set, dismiss the keyguard right away } isUserSwitchUiEnabled && !mInjector.getKeyguardManager().isDeviceSecure(newUserId), mInjector::dismissKeyguard, () -> await( // STEP 2 - If user switch ui was enabled, dismiss user switch dialog isUserSwitchUiEnabled, this::dismissUserSwitchDialog, () -> { // STEP 3 - Send REPORT_USER_SWITCH_COMPLETE_MSG to broadcast // ACTION_USER_SWITCHED & call UserSwitchObservers.onUserSwitchComplete mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG); mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG); mHandler.sendMessage(mHandler.obtainMessage( mHandler.sendMessage(mHandler.obtainMessage( REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId)); REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId)); }; // If there is no challenge set, dismiss the keyguard right away if (isUserSwitchUiEnabled && !mInjector.getKeyguardManager().isDeviceSecure(newUserId)) { // Wait until the keyguard is dismissed to unfreeze mInjector.dismissKeyguard(runnable); } else { runnable.run(); } } )); } } /** private void await(boolean condition, Consumer<Runnable> conditionalStep, Runnable nextStep) { * Tell WindowManager we're ready to unfreeze the screen, at its leisure. Note that there is if (condition) { * likely a lot going on, and WM won't unfreeze until the drawing is all done, so conditionalStep.accept(nextStep); * the actual unfreeze may still not happen for a long time; this is expected. } else { */ nextStep.run(); @VisibleForTesting } void unfreezeScreen() { TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("stopFreezingScreen"); mInjector.getWindowManager().stopFreezingScreen(); t.traceEnd(); } } private void moveUserToForeground(UserState uss, int newUserId) { private void moveUserToForeground(UserState uss, int newUserId) { Loading Loading @@ -3731,17 +3724,18 @@ class UserController implements Handler.Callback { mService.mCpHelper.installEncryptionUnawareProviders(userId); mService.mCpHelper.installEncryptionUnawareProviders(userId); } } void dismissUserSwitchingDialog() { void dismissUserSwitchingDialog(@Nullable Runnable onDismissed) { synchronized (mUserSwitchingDialogLock) { synchronized (mUserSwitchingDialogLock) { if (mUserSwitchingDialog != null) { if (mUserSwitchingDialog != null) { mUserSwitchingDialog.dismiss(); mUserSwitchingDialog.dismiss(onDismissed); mUserSwitchingDialog = null; mUserSwitchingDialog = null; } } } } } } void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, String switchingFromSystemUserMessage, String switchingToSystemUserMessage) { String switchingFromSystemUserMessage, String switchingToSystemUserMessage, @NonNull Runnable onShown) { if (mService.mContext.getPackageManager() if (mService.mContext.getPackageManager() .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { // config_customUserSwitchUi is set to true on Automotive as CarSystemUI is // config_customUserSwitchUi is set to true on Automotive as CarSystemUI is Loading @@ -3751,11 +3745,10 @@ class UserController implements Handler.Callback { + "condition if it's shown by CarSystemUI as well"); + "condition if it's shown by CarSystemUI as well"); } } synchronized (mUserSwitchingDialogLock) { synchronized (mUserSwitchingDialogLock) { dismissUserSwitchingDialog(); dismissUserSwitchingDialog(null); mUserSwitchingDialog = new UserSwitchingDialog(mService, mService.mContext, mUserSwitchingDialog = new UserSwitchingDialog(mService.mContext, fromUser, toUser, fromUser, toUser, true /* above system */, switchingFromSystemUserMessage, switchingFromSystemUserMessage, switchingToSystemUserMessage); switchingToSystemUserMessage); mUserSwitchingDialog.show(onShown); mUserSwitchingDialog.show(); } } } } Loading
services/core/java/com/android/server/am/UserSwitchingDialog.java +201 −103 File changed.Preview size limit exceeded, changes collapsed. Show changes