Loading packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java +133 −69 Original line number Diff line number Diff line Loading @@ -25,21 +25,24 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; import android.content.res.Resources; import android.os.UserHandle; import com.android.internal.logging.UiEventLogger; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.qs.QSUserSwitcherEvent; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.UserSwitcherController; import javax.inject.Inject; import dagger.Lazy; import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; import dagger.assisted.AssistedInject; import javax.inject.Inject; /** * Manages handling of guest session persistent notification * and actions to reset guest or exit guest session Loading Loading @@ -70,14 +73,14 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { public AlertDialog mResetSessionDialog; private final UserTracker mUserTracker; private final BroadcastDispatcher mBroadcastDispatcher; private final ResetSessionDialog.Factory mResetSessionDialogFactory; private final ExitSessionDialog.Factory mExitSessionDialogFactory; private final ResetSessionDialogFactory mResetSessionDialogFactory; private final ExitSessionDialogFactory mExitSessionDialogFactory; @Inject public GuestResetOrExitSessionReceiver(UserTracker userTracker, BroadcastDispatcher broadcastDispatcher, ResetSessionDialog.Factory resetSessionDialogFactory, ExitSessionDialog.Factory exitSessionDialogFactory) { ResetSessionDialogFactory resetSessionDialogFactory, ExitSessionDialogFactory exitSessionDialogFactory) { mUserTracker = userTracker; mBroadcastDispatcher = broadcastDispatcher; mResetSessionDialogFactory = resetSessionDialogFactory; Loading Loading @@ -111,8 +114,8 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mResetSessionDialog = mResetSessionDialogFactory.create(currentUser.id); mResetSessionDialog.show(); } else if (ACTION_GUEST_EXIT.equals(action)) { mExitSessionDialog = mExitSessionDialogFactory.create(currentUser.id, currentUser.isEphemeral()); mExitSessionDialog = mExitSessionDialogFactory.create( currentUser.isEphemeral(), currentUser.id); mExitSessionDialog.show(); } } Loading @@ -132,43 +135,69 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { } /** * Factory class to create guest reset dialog instance * * Dialog shown when asking for confirmation before * reset and restart of guest user. */ public static final class ResetSessionDialog extends SystemUIDialog implements DialogInterface.OnClickListener { public static final class ResetSessionDialogFactory { private final Lazy<SystemUIDialog> mDialogLazy; private final Resources mResources; private final ResetSessionDialogClickListener.Factory mClickListenerFactory; @Inject public ResetSessionDialogFactory( Lazy<SystemUIDialog> dialogLazy, @Main Resources resources, ResetSessionDialogClickListener.Factory clickListenerFactory) { mDialogLazy = dialogLazy; mResources = resources; mClickListenerFactory = clickListenerFactory; } /** Create a guest reset dialog instance */ public AlertDialog create(int userId) { SystemUIDialog dialog = mDialogLazy.get(); ResetSessionDialogClickListener listener = mClickListenerFactory.create( userId, dialog); dialog.setTitle(com.android.settingslib.R.string.guest_reset_and_restart_dialog_title); dialog.setMessage(mResources.getString( com.android.settingslib.R.string.guest_reset_and_restart_dialog_message)); dialog.setButton( DialogInterface.BUTTON_NEUTRAL, mResources.getString(android.R.string.cancel), listener); dialog.setButton(DialogInterface.BUTTON_POSITIVE, mResources.getString( com.android.settingslib.R.string.guest_reset_guest_confirm_button), listener); dialog.setCanceledOnTouchOutside(false); return dialog; } } public static class ResetSessionDialogClickListener implements DialogInterface.OnClickListener { private final UserSwitcherController mUserSwitcherController; private final UiEventLogger mUiEventLogger; private final int mUserId; private final DialogInterface mDialog; /** Factory class to create guest reset dialog instance */ @AssistedFactory public interface Factory { /** Create a guest reset dialog instance */ ResetSessionDialog create(int userId); ResetSessionDialogClickListener create(int userId, DialogInterface dialog); } @AssistedInject ResetSessionDialog(Context context, public ResetSessionDialogClickListener( UserSwitcherController userSwitcherController, UiEventLogger uiEventLogger, @Assisted int userId) { super(context); setTitle(com.android.settingslib.R.string.guest_reset_and_restart_dialog_title); setMessage(context.getString( com.android.settingslib.R.string.guest_reset_and_restart_dialog_message)); setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel), this); setButton(DialogInterface.BUTTON_POSITIVE, context.getString( com.android.settingslib.R.string.guest_reset_guest_confirm_button), this); setCanceledOnTouchOutside(false); @Assisted int userId, @Assisted DialogInterface dialog ) { mUserSwitcherController = userSwitcherController; mUiEventLogger = uiEventLogger; mUserId = userId; mDialog = dialog; } @Override Loading @@ -177,7 +206,7 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE); mUserSwitcherController.removeGuestUser(mUserId, UserHandle.USER_NULL); } else if (which == DialogInterface.BUTTON_NEUTRAL) { cancel(); mDialog.cancel(); } } } Loading @@ -186,58 +215,93 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { * Dialog shown when asking for confirmation before * exit of guest user. */ public static final class ExitSessionDialog extends SystemUIDialog implements DialogInterface.OnClickListener { public static final class ExitSessionDialogFactory { private final Lazy<SystemUIDialog> mDialogLazy; private final ExitSessionDialogClickListener.Factory mClickListenerFactory; private final Resources mResources; private final UserSwitcherController mUserSwitcherController; private final int mUserId; private boolean mIsEphemeral; /** Factory class to create guest exit dialog instance */ @AssistedFactory public interface Factory { /** Create a guest exit dialog instance */ ExitSessionDialog create(int userId, boolean isEphemeral); @Inject public ExitSessionDialogFactory( Lazy<SystemUIDialog> dialogLazy, ExitSessionDialogClickListener.Factory clickListenerFactory, @Main Resources resources) { mDialogLazy = dialogLazy; mClickListenerFactory = clickListenerFactory; mResources = resources; } @AssistedInject ExitSessionDialog(Context context, UserSwitcherController userSwitcherController, @Assisted int userId, @Assisted boolean isEphemeral) { super(context); public AlertDialog create(boolean isEphemeral, int userId) { SystemUIDialog dialog = mDialogLazy.get(); ExitSessionDialogClickListener clickListener = mClickListenerFactory.create( isEphemeral, userId, dialog); if (isEphemeral) { setTitle(context.getString( dialog.setTitle(mResources.getString( com.android.settingslib.R.string.guest_exit_dialog_title)); setMessage(context.getString( dialog.setMessage(mResources.getString( com.android.settingslib.R.string.guest_exit_dialog_message)); setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel), this); setButton(DialogInterface.BUTTON_POSITIVE, context.getString( com.android.settingslib.R.string.guest_exit_dialog_button), this); dialog.setButton( DialogInterface.BUTTON_NEUTRAL, mResources.getString(android.R.string.cancel), clickListener); dialog.setButton( DialogInterface.BUTTON_POSITIVE, mResources.getString( com.android.settingslib.R.string.guest_exit_dialog_button), clickListener); } else { setTitle(context.getString( dialog.setTitle(mResources.getString( com.android.settingslib .R.string.guest_exit_dialog_title_non_ephemeral)); setMessage(context.getString( dialog.setMessage(mResources.getString( com.android.settingslib .R.string.guest_exit_dialog_message_non_ephemeral)); setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel), this); setButton(DialogInterface.BUTTON_NEGATIVE, context.getString( com.android.settingslib.R.string.guest_exit_clear_data_button), this); setButton(DialogInterface.BUTTON_POSITIVE, context.getString( com.android.settingslib.R.string.guest_exit_save_data_button), this); dialog.setButton( DialogInterface.BUTTON_NEUTRAL, mResources.getString(android.R.string.cancel), clickListener); dialog.setButton( DialogInterface.BUTTON_NEGATIVE, mResources.getString( com.android.settingslib.R.string.guest_exit_clear_data_button), clickListener); dialog.setButton( DialogInterface.BUTTON_POSITIVE, mResources.getString( com.android.settingslib.R.string.guest_exit_save_data_button), clickListener); } dialog.setCanceledOnTouchOutside(false); return dialog; } } public static class ExitSessionDialogClickListener implements DialogInterface.OnClickListener { private final UserSwitcherController mUserSwitcherController; private final boolean mIsEphemeral; private final int mUserId; private final DialogInterface mDialog; @AssistedFactory public interface Factory { ExitSessionDialogClickListener create( boolean isEphemeral, int userId, DialogInterface dialog); } setCanceledOnTouchOutside(false); @AssistedInject public ExitSessionDialogClickListener( UserSwitcherController userSwitcherController, @Assisted boolean isEphemeral, @Assisted int userId, @Assisted DialogInterface dialog ) { mUserSwitcherController = userSwitcherController; mUserId = userId; mIsEphemeral = isEphemeral; mUserId = userId; mDialog = dialog; } @Override Loading @@ -249,7 +313,7 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mUserSwitcherController.exitGuestUser(mUserId, UserHandle.USER_NULL, false); } else if (which == DialogInterface.BUTTON_NEUTRAL) { // Cancel clicked, do nothing cancel(); mDialog.cancel(); } } else { if (which == DialogInterface.BUTTON_POSITIVE) { Loading @@ -261,7 +325,7 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mUserSwitcherController.exitGuestUser(mUserId, UserHandle.USER_NULL, true); } else if (which == DialogInterface.BUTTON_NEUTRAL) { // Cancel clicked, do nothing cancel(); mDialog.cancel(); } } } Loading packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java +7 −6 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.annotation.NonNull; import com.android.systemui.res.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.systemui.GuestResetOrExitSessionReceiver.ResetSessionDialogFactory; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; Loading @@ -36,14 +37,14 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.util.settings.SecureSettings; import java.util.concurrent.Executor; import javax.inject.Inject; import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; import dagger.assisted.AssistedInject; import java.util.concurrent.Executor; import javax.inject.Inject; /** * Manages notification when a guest session is resumed. */ Loading @@ -58,7 +59,7 @@ public class GuestResumeSessionReceiver { private final Executor mMainExecutor; private final UserTracker mUserTracker; private final SecureSettings mSecureSettings; private final ResetSessionDialog.Factory mResetSessionDialogFactory; private final ResetSessionDialogFactory mResetSessionDialogFactory; private final GuestSessionNotification mGuestSessionNotification; @VisibleForTesting Loading Loading @@ -104,7 +105,7 @@ public class GuestResumeSessionReceiver { UserTracker userTracker, SecureSettings secureSettings, GuestSessionNotification guestSessionNotification, ResetSessionDialog.Factory resetSessionDialogFactory) { ResetSessionDialogFactory resetSessionDialogFactory) { mMainExecutor = mainExecutor; mUserTracker = userTracker; mSecureSettings = secureSettings; Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java +149 −6 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.systemui.Dependency; import com.android.systemui.res.R; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Application; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.model.SysUiState; Loading @@ -54,8 +55,14 @@ import com.android.systemui.util.DialogKt; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; /** * Base class for dialogs that should appear over panels and keyguard. * Class for dialogs that should appear over panels and keyguard. * * DO NOT SUBCLASS THIS. See {@link SystemUIDialog.Delegate} for an interface that enables * customizing behavior via composition instead of inheritance. Clients should implement the * Delegate class and then pass their implementation into the SystemUIDialog constructor. * * Optionally provide a {@link SystemUIDialogManager} to its constructor to send signals to * listeners on whether this dialog is showing. Loading @@ -72,6 +79,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh private final Context mContext; private final FeatureFlags mFeatureFlags; private final Delegate mDelegate; @Nullable private final DismissReceiver mDismissReceiver; private final Handler mHandler = new Handler(); private final SystemUIDialogManager mDialogManager; Loading Loading @@ -101,18 +109,102 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh Dependency.get(SystemUIDialogManager.class), Dependency.get(SysUiState.class), Dependency.get(BroadcastDispatcher.class), Dependency.get(DialogLaunchAnimator.class)); Dependency.get(DialogLaunchAnimator.class), new Delegate() {}); } @Inject public SystemUIDialog( @Application Context context, FeatureFlags featureFlags, SystemUIDialogManager systemUIDialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { this(context, DEFAULT_THEME, DEFAULT_DISMISS_ON_DEVICE_LOCK, featureFlags, systemUIDialogManager, sysUiState, broadcastDispatcher, dialogLaunchAnimator, new Delegate(){}); } public static class Factory { private final Context mContext; private final FeatureFlags mFeatureFlags; private final SystemUIDialogManager mSystemUIDialogManager; private final SysUiState mSysUiState; private final BroadcastDispatcher mBroadcastDispatcher; private final DialogLaunchAnimator mDialogLaunchAnimator; @Inject public Factory( @Application Context context, FeatureFlags featureFlags, SystemUIDialogManager systemUIDialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { mContext = context; mFeatureFlags = featureFlags; mSystemUIDialogManager = systemUIDialogManager; mSysUiState = sysUiState; mBroadcastDispatcher = broadcastDispatcher; mDialogLaunchAnimator = dialogLaunchAnimator; } public SystemUIDialog create(Delegate delegate) { return new SystemUIDialog( mContext, DEFAULT_THEME, DEFAULT_DISMISS_ON_DEVICE_LOCK, mFeatureFlags, mSystemUIDialogManager, mSysUiState, mBroadcastDispatcher, mDialogLaunchAnimator, delegate); } } public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock, public SystemUIDialog( Context context, int theme, boolean dismissOnDeviceLock, FeatureFlags featureFlags, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { this( context, theme, dismissOnDeviceLock, featureFlags, dialogManager, sysUiState, broadcastDispatcher, dialogLaunchAnimator, new Delegate(){}); } public SystemUIDialog( Context context, int theme, boolean dismissOnDeviceLock, FeatureFlags featureFlags, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator, Delegate delegate) { super(context, theme); mContext = context; mFeatureFlags = featureFlags; mDelegate = delegate; applyFlags(this); WindowManager.LayoutParams attrs = getWindow().getAttributes(); Loading @@ -127,7 +219,9 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh @Override protected void onCreate(Bundle savedInstanceState) { mDelegate.beforeCreate(this, savedInstanceState); super.onCreate(savedInstanceState); mDelegate.onCreate(this, savedInstanceState); Configuration config = getContext().getResources().getConfiguration(); mLastConfigurationWidthDp = config.screenWidthDp; Loading Loading @@ -172,6 +266,8 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh updateWindowSize(); } mDelegate.onConfigurationChanged(this, configuration); } /** Loading Loading @@ -212,7 +308,9 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh * Called when {@link #onStart} is called. Subclasses wishing to override {@link #onStart()} * should override this method instead. */ protected void start() {} protected void start() { mDelegate.start(this); } @Override protected final void onStop() { Loading @@ -234,7 +332,15 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh * Called when {@link #onStop} is called. Subclasses wishing to override {@link #onStop()} * should override this method instead. */ protected void stop() {} protected void stop() { mDelegate.stop(this); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); mDelegate.onWindowFocusChanged(this, hasFocus); } public void setShowForAllUsers(boolean show) { setShowForAllUsers(this, show); Loading Loading @@ -353,7 +459,6 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh registerDismissListener(dialog, null); } /** * Registers a listener that dismisses the given dialog when it receives * the screen off / close system dialogs broadcast. Loading Loading @@ -480,4 +585,42 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh } } /** * A delegate class that should be implemented in place of sublcassing {@link SystemUIDialog}. * * Implement this interface and then pass an instance of your implementation to * {@link SystemUIDialog.Factory#create(Delegate)}. */ public interface Delegate { /** * Called before {@link AlertDialog#onCreate} is called. */ default void beforeCreate(SystemUIDialog dialog, Bundle savedInstanceState) {} /** * Called after {@link AlertDialog#onCreate} is called. */ default void onCreate(SystemUIDialog dialog, Bundle savedInstanceState) {} /** * Called after {@link AlertDialog#onStart} is called. */ default void start(SystemUIDialog dialog) {} /** * Called after {@link AlertDialog#onStop} is called. */ default void stop(SystemUIDialog dialog) {} /** * Called after {@link AlertDialog#onWindowFocusChanged(boolean)} is called. */ default void onWindowFocusChanged(SystemUIDialog dialog, boolean hasFocus) {} /** * Called as part of * {@link ViewRootImpl.ConfigChangedCallback#onConfigurationChanged(Configuration)}. */ default void onConfigurationChanged(SystemUIDialog dialog, Configuration configuration) {} } } packages/SystemUI/tests/src/com/android/SysUITestModule.kt +5 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,12 @@ package com.android import android.content.Context import android.content.res.Resources import com.android.systemui.FakeSystemUiModule import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import dagger.Module import dagger.Provides Loading @@ -36,6 +38,9 @@ class SysUITestModule { @Provides @Application fun provideAppContext(test: SysuiTestCase): Context = test.context @Provides @Main fun provideResources(@Application context: Context): Resources = context.resources @Provides fun provideBroadcastDispatcher(test: SysuiTestCase): BroadcastDispatcher = test.fakeBroadcastDispatcher Loading packages/SystemUI/tests/src/com/android/TestMocksModule.kt +6 −0 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ import android.util.DisplayMetrics import com.android.internal.logging.MetricsLogger import com.android.keyguard.KeyguardSecurityModel import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardViewController import com.android.systemui.GuestResumeSessionReceiver import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.demomode.DemoModeController import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.ScreenLifecycle Loading @@ -31,6 +33,7 @@ import com.android.systemui.log.LogBuffer import com.android.systemui.log.dagger.BroadcastDispatcherLog import com.android.systemui.log.dagger.SceneFrameworkLog import com.android.systemui.media.controls.ui.MediaHierarchyManager import com.android.systemui.model.SysUiState import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.plugins.statusbar.StatusBarStateController Loading Loading @@ -86,6 +89,9 @@ data class TestMocksModule( @get:Provides val statusBarStateController: SysuiStatusBarStateController = mock(), @get:Provides val statusBarWindowController: StatusBarWindowController = mock(), @get:Provides val wakefulnessLifecycle: WakefulnessLifecycle = mock(), @get:Provides val keyguardViewController: KeyguardViewController = mock(), @get:Provides val dialogLaunchAnimator: DialogLaunchAnimator = mock(), @get:Provides val sysuiState: SysUiState = mock(), // log buffers @get:[Provides BroadcastDispatcherLog] Loading Loading
packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java +133 −69 Original line number Diff line number Diff line Loading @@ -25,21 +25,24 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; import android.content.res.Resources; import android.os.UserHandle; import com.android.internal.logging.UiEventLogger; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.qs.QSUserSwitcherEvent; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.UserSwitcherController; import javax.inject.Inject; import dagger.Lazy; import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; import dagger.assisted.AssistedInject; import javax.inject.Inject; /** * Manages handling of guest session persistent notification * and actions to reset guest or exit guest session Loading Loading @@ -70,14 +73,14 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { public AlertDialog mResetSessionDialog; private final UserTracker mUserTracker; private final BroadcastDispatcher mBroadcastDispatcher; private final ResetSessionDialog.Factory mResetSessionDialogFactory; private final ExitSessionDialog.Factory mExitSessionDialogFactory; private final ResetSessionDialogFactory mResetSessionDialogFactory; private final ExitSessionDialogFactory mExitSessionDialogFactory; @Inject public GuestResetOrExitSessionReceiver(UserTracker userTracker, BroadcastDispatcher broadcastDispatcher, ResetSessionDialog.Factory resetSessionDialogFactory, ExitSessionDialog.Factory exitSessionDialogFactory) { ResetSessionDialogFactory resetSessionDialogFactory, ExitSessionDialogFactory exitSessionDialogFactory) { mUserTracker = userTracker; mBroadcastDispatcher = broadcastDispatcher; mResetSessionDialogFactory = resetSessionDialogFactory; Loading Loading @@ -111,8 +114,8 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mResetSessionDialog = mResetSessionDialogFactory.create(currentUser.id); mResetSessionDialog.show(); } else if (ACTION_GUEST_EXIT.equals(action)) { mExitSessionDialog = mExitSessionDialogFactory.create(currentUser.id, currentUser.isEphemeral()); mExitSessionDialog = mExitSessionDialogFactory.create( currentUser.isEphemeral(), currentUser.id); mExitSessionDialog.show(); } } Loading @@ -132,43 +135,69 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { } /** * Factory class to create guest reset dialog instance * * Dialog shown when asking for confirmation before * reset and restart of guest user. */ public static final class ResetSessionDialog extends SystemUIDialog implements DialogInterface.OnClickListener { public static final class ResetSessionDialogFactory { private final Lazy<SystemUIDialog> mDialogLazy; private final Resources mResources; private final ResetSessionDialogClickListener.Factory mClickListenerFactory; @Inject public ResetSessionDialogFactory( Lazy<SystemUIDialog> dialogLazy, @Main Resources resources, ResetSessionDialogClickListener.Factory clickListenerFactory) { mDialogLazy = dialogLazy; mResources = resources; mClickListenerFactory = clickListenerFactory; } /** Create a guest reset dialog instance */ public AlertDialog create(int userId) { SystemUIDialog dialog = mDialogLazy.get(); ResetSessionDialogClickListener listener = mClickListenerFactory.create( userId, dialog); dialog.setTitle(com.android.settingslib.R.string.guest_reset_and_restart_dialog_title); dialog.setMessage(mResources.getString( com.android.settingslib.R.string.guest_reset_and_restart_dialog_message)); dialog.setButton( DialogInterface.BUTTON_NEUTRAL, mResources.getString(android.R.string.cancel), listener); dialog.setButton(DialogInterface.BUTTON_POSITIVE, mResources.getString( com.android.settingslib.R.string.guest_reset_guest_confirm_button), listener); dialog.setCanceledOnTouchOutside(false); return dialog; } } public static class ResetSessionDialogClickListener implements DialogInterface.OnClickListener { private final UserSwitcherController mUserSwitcherController; private final UiEventLogger mUiEventLogger; private final int mUserId; private final DialogInterface mDialog; /** Factory class to create guest reset dialog instance */ @AssistedFactory public interface Factory { /** Create a guest reset dialog instance */ ResetSessionDialog create(int userId); ResetSessionDialogClickListener create(int userId, DialogInterface dialog); } @AssistedInject ResetSessionDialog(Context context, public ResetSessionDialogClickListener( UserSwitcherController userSwitcherController, UiEventLogger uiEventLogger, @Assisted int userId) { super(context); setTitle(com.android.settingslib.R.string.guest_reset_and_restart_dialog_title); setMessage(context.getString( com.android.settingslib.R.string.guest_reset_and_restart_dialog_message)); setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel), this); setButton(DialogInterface.BUTTON_POSITIVE, context.getString( com.android.settingslib.R.string.guest_reset_guest_confirm_button), this); setCanceledOnTouchOutside(false); @Assisted int userId, @Assisted DialogInterface dialog ) { mUserSwitcherController = userSwitcherController; mUiEventLogger = uiEventLogger; mUserId = userId; mDialog = dialog; } @Override Loading @@ -177,7 +206,7 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE); mUserSwitcherController.removeGuestUser(mUserId, UserHandle.USER_NULL); } else if (which == DialogInterface.BUTTON_NEUTRAL) { cancel(); mDialog.cancel(); } } } Loading @@ -186,58 +215,93 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { * Dialog shown when asking for confirmation before * exit of guest user. */ public static final class ExitSessionDialog extends SystemUIDialog implements DialogInterface.OnClickListener { public static final class ExitSessionDialogFactory { private final Lazy<SystemUIDialog> mDialogLazy; private final ExitSessionDialogClickListener.Factory mClickListenerFactory; private final Resources mResources; private final UserSwitcherController mUserSwitcherController; private final int mUserId; private boolean mIsEphemeral; /** Factory class to create guest exit dialog instance */ @AssistedFactory public interface Factory { /** Create a guest exit dialog instance */ ExitSessionDialog create(int userId, boolean isEphemeral); @Inject public ExitSessionDialogFactory( Lazy<SystemUIDialog> dialogLazy, ExitSessionDialogClickListener.Factory clickListenerFactory, @Main Resources resources) { mDialogLazy = dialogLazy; mClickListenerFactory = clickListenerFactory; mResources = resources; } @AssistedInject ExitSessionDialog(Context context, UserSwitcherController userSwitcherController, @Assisted int userId, @Assisted boolean isEphemeral) { super(context); public AlertDialog create(boolean isEphemeral, int userId) { SystemUIDialog dialog = mDialogLazy.get(); ExitSessionDialogClickListener clickListener = mClickListenerFactory.create( isEphemeral, userId, dialog); if (isEphemeral) { setTitle(context.getString( dialog.setTitle(mResources.getString( com.android.settingslib.R.string.guest_exit_dialog_title)); setMessage(context.getString( dialog.setMessage(mResources.getString( com.android.settingslib.R.string.guest_exit_dialog_message)); setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel), this); setButton(DialogInterface.BUTTON_POSITIVE, context.getString( com.android.settingslib.R.string.guest_exit_dialog_button), this); dialog.setButton( DialogInterface.BUTTON_NEUTRAL, mResources.getString(android.R.string.cancel), clickListener); dialog.setButton( DialogInterface.BUTTON_POSITIVE, mResources.getString( com.android.settingslib.R.string.guest_exit_dialog_button), clickListener); } else { setTitle(context.getString( dialog.setTitle(mResources.getString( com.android.settingslib .R.string.guest_exit_dialog_title_non_ephemeral)); setMessage(context.getString( dialog.setMessage(mResources.getString( com.android.settingslib .R.string.guest_exit_dialog_message_non_ephemeral)); setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel), this); setButton(DialogInterface.BUTTON_NEGATIVE, context.getString( com.android.settingslib.R.string.guest_exit_clear_data_button), this); setButton(DialogInterface.BUTTON_POSITIVE, context.getString( com.android.settingslib.R.string.guest_exit_save_data_button), this); dialog.setButton( DialogInterface.BUTTON_NEUTRAL, mResources.getString(android.R.string.cancel), clickListener); dialog.setButton( DialogInterface.BUTTON_NEGATIVE, mResources.getString( com.android.settingslib.R.string.guest_exit_clear_data_button), clickListener); dialog.setButton( DialogInterface.BUTTON_POSITIVE, mResources.getString( com.android.settingslib.R.string.guest_exit_save_data_button), clickListener); } dialog.setCanceledOnTouchOutside(false); return dialog; } } public static class ExitSessionDialogClickListener implements DialogInterface.OnClickListener { private final UserSwitcherController mUserSwitcherController; private final boolean mIsEphemeral; private final int mUserId; private final DialogInterface mDialog; @AssistedFactory public interface Factory { ExitSessionDialogClickListener create( boolean isEphemeral, int userId, DialogInterface dialog); } setCanceledOnTouchOutside(false); @AssistedInject public ExitSessionDialogClickListener( UserSwitcherController userSwitcherController, @Assisted boolean isEphemeral, @Assisted int userId, @Assisted DialogInterface dialog ) { mUserSwitcherController = userSwitcherController; mUserId = userId; mIsEphemeral = isEphemeral; mUserId = userId; mDialog = dialog; } @Override Loading @@ -249,7 +313,7 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mUserSwitcherController.exitGuestUser(mUserId, UserHandle.USER_NULL, false); } else if (which == DialogInterface.BUTTON_NEUTRAL) { // Cancel clicked, do nothing cancel(); mDialog.cancel(); } } else { if (which == DialogInterface.BUTTON_POSITIVE) { Loading @@ -261,7 +325,7 @@ public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { mUserSwitcherController.exitGuestUser(mUserId, UserHandle.USER_NULL, true); } else if (which == DialogInterface.BUTTON_NEUTRAL) { // Cancel clicked, do nothing cancel(); mDialog.cancel(); } } } Loading
packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java +7 −6 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.annotation.NonNull; import com.android.systemui.res.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.systemui.GuestResetOrExitSessionReceiver.ResetSessionDialogFactory; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; Loading @@ -36,14 +37,14 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.util.settings.SecureSettings; import java.util.concurrent.Executor; import javax.inject.Inject; import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; import dagger.assisted.AssistedInject; import java.util.concurrent.Executor; import javax.inject.Inject; /** * Manages notification when a guest session is resumed. */ Loading @@ -58,7 +59,7 @@ public class GuestResumeSessionReceiver { private final Executor mMainExecutor; private final UserTracker mUserTracker; private final SecureSettings mSecureSettings; private final ResetSessionDialog.Factory mResetSessionDialogFactory; private final ResetSessionDialogFactory mResetSessionDialogFactory; private final GuestSessionNotification mGuestSessionNotification; @VisibleForTesting Loading Loading @@ -104,7 +105,7 @@ public class GuestResumeSessionReceiver { UserTracker userTracker, SecureSettings secureSettings, GuestSessionNotification guestSessionNotification, ResetSessionDialog.Factory resetSessionDialogFactory) { ResetSessionDialogFactory resetSessionDialogFactory) { mMainExecutor = mainExecutor; mUserTracker = userTracker; mSecureSettings = secureSettings; Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java +149 −6 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.systemui.Dependency; import com.android.systemui.res.R; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Application; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.model.SysUiState; Loading @@ -54,8 +55,14 @@ import com.android.systemui.util.DialogKt; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; /** * Base class for dialogs that should appear over panels and keyguard. * Class for dialogs that should appear over panels and keyguard. * * DO NOT SUBCLASS THIS. See {@link SystemUIDialog.Delegate} for an interface that enables * customizing behavior via composition instead of inheritance. Clients should implement the * Delegate class and then pass their implementation into the SystemUIDialog constructor. * * Optionally provide a {@link SystemUIDialogManager} to its constructor to send signals to * listeners on whether this dialog is showing. Loading @@ -72,6 +79,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh private final Context mContext; private final FeatureFlags mFeatureFlags; private final Delegate mDelegate; @Nullable private final DismissReceiver mDismissReceiver; private final Handler mHandler = new Handler(); private final SystemUIDialogManager mDialogManager; Loading Loading @@ -101,18 +109,102 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh Dependency.get(SystemUIDialogManager.class), Dependency.get(SysUiState.class), Dependency.get(BroadcastDispatcher.class), Dependency.get(DialogLaunchAnimator.class)); Dependency.get(DialogLaunchAnimator.class), new Delegate() {}); } @Inject public SystemUIDialog( @Application Context context, FeatureFlags featureFlags, SystemUIDialogManager systemUIDialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { this(context, DEFAULT_THEME, DEFAULT_DISMISS_ON_DEVICE_LOCK, featureFlags, systemUIDialogManager, sysUiState, broadcastDispatcher, dialogLaunchAnimator, new Delegate(){}); } public static class Factory { private final Context mContext; private final FeatureFlags mFeatureFlags; private final SystemUIDialogManager mSystemUIDialogManager; private final SysUiState mSysUiState; private final BroadcastDispatcher mBroadcastDispatcher; private final DialogLaunchAnimator mDialogLaunchAnimator; @Inject public Factory( @Application Context context, FeatureFlags featureFlags, SystemUIDialogManager systemUIDialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { mContext = context; mFeatureFlags = featureFlags; mSystemUIDialogManager = systemUIDialogManager; mSysUiState = sysUiState; mBroadcastDispatcher = broadcastDispatcher; mDialogLaunchAnimator = dialogLaunchAnimator; } public SystemUIDialog create(Delegate delegate) { return new SystemUIDialog( mContext, DEFAULT_THEME, DEFAULT_DISMISS_ON_DEVICE_LOCK, mFeatureFlags, mSystemUIDialogManager, mSysUiState, mBroadcastDispatcher, mDialogLaunchAnimator, delegate); } } public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock, public SystemUIDialog( Context context, int theme, boolean dismissOnDeviceLock, FeatureFlags featureFlags, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { this( context, theme, dismissOnDeviceLock, featureFlags, dialogManager, sysUiState, broadcastDispatcher, dialogLaunchAnimator, new Delegate(){}); } public SystemUIDialog( Context context, int theme, boolean dismissOnDeviceLock, FeatureFlags featureFlags, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator, Delegate delegate) { super(context, theme); mContext = context; mFeatureFlags = featureFlags; mDelegate = delegate; applyFlags(this); WindowManager.LayoutParams attrs = getWindow().getAttributes(); Loading @@ -127,7 +219,9 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh @Override protected void onCreate(Bundle savedInstanceState) { mDelegate.beforeCreate(this, savedInstanceState); super.onCreate(savedInstanceState); mDelegate.onCreate(this, savedInstanceState); Configuration config = getContext().getResources().getConfiguration(); mLastConfigurationWidthDp = config.screenWidthDp; Loading Loading @@ -172,6 +266,8 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh updateWindowSize(); } mDelegate.onConfigurationChanged(this, configuration); } /** Loading Loading @@ -212,7 +308,9 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh * Called when {@link #onStart} is called. Subclasses wishing to override {@link #onStart()} * should override this method instead. */ protected void start() {} protected void start() { mDelegate.start(this); } @Override protected final void onStop() { Loading @@ -234,7 +332,15 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh * Called when {@link #onStop} is called. Subclasses wishing to override {@link #onStop()} * should override this method instead. */ protected void stop() {} protected void stop() { mDelegate.stop(this); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); mDelegate.onWindowFocusChanged(this, hasFocus); } public void setShowForAllUsers(boolean show) { setShowForAllUsers(this, show); Loading Loading @@ -353,7 +459,6 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh registerDismissListener(dialog, null); } /** * Registers a listener that dismisses the given dialog when it receives * the screen off / close system dialogs broadcast. Loading Loading @@ -480,4 +585,42 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh } } /** * A delegate class that should be implemented in place of sublcassing {@link SystemUIDialog}. * * Implement this interface and then pass an instance of your implementation to * {@link SystemUIDialog.Factory#create(Delegate)}. */ public interface Delegate { /** * Called before {@link AlertDialog#onCreate} is called. */ default void beforeCreate(SystemUIDialog dialog, Bundle savedInstanceState) {} /** * Called after {@link AlertDialog#onCreate} is called. */ default void onCreate(SystemUIDialog dialog, Bundle savedInstanceState) {} /** * Called after {@link AlertDialog#onStart} is called. */ default void start(SystemUIDialog dialog) {} /** * Called after {@link AlertDialog#onStop} is called. */ default void stop(SystemUIDialog dialog) {} /** * Called after {@link AlertDialog#onWindowFocusChanged(boolean)} is called. */ default void onWindowFocusChanged(SystemUIDialog dialog, boolean hasFocus) {} /** * Called as part of * {@link ViewRootImpl.ConfigChangedCallback#onConfigurationChanged(Configuration)}. */ default void onConfigurationChanged(SystemUIDialog dialog, Configuration configuration) {} } }
packages/SystemUI/tests/src/com/android/SysUITestModule.kt +5 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,12 @@ package com.android import android.content.Context import android.content.res.Resources import com.android.systemui.FakeSystemUiModule import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import dagger.Module import dagger.Provides Loading @@ -36,6 +38,9 @@ class SysUITestModule { @Provides @Application fun provideAppContext(test: SysuiTestCase): Context = test.context @Provides @Main fun provideResources(@Application context: Context): Resources = context.resources @Provides fun provideBroadcastDispatcher(test: SysuiTestCase): BroadcastDispatcher = test.fakeBroadcastDispatcher Loading
packages/SystemUI/tests/src/com/android/TestMocksModule.kt +6 −0 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ import android.util.DisplayMetrics import com.android.internal.logging.MetricsLogger import com.android.keyguard.KeyguardSecurityModel import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardViewController import com.android.systemui.GuestResumeSessionReceiver import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.demomode.DemoModeController import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.ScreenLifecycle Loading @@ -31,6 +33,7 @@ import com.android.systemui.log.LogBuffer import com.android.systemui.log.dagger.BroadcastDispatcherLog import com.android.systemui.log.dagger.SceneFrameworkLog import com.android.systemui.media.controls.ui.MediaHierarchyManager import com.android.systemui.model.SysUiState import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.plugins.statusbar.StatusBarStateController Loading Loading @@ -86,6 +89,9 @@ data class TestMocksModule( @get:Provides val statusBarStateController: SysuiStatusBarStateController = mock(), @get:Provides val statusBarWindowController: StatusBarWindowController = mock(), @get:Provides val wakefulnessLifecycle: WakefulnessLifecycle = mock(), @get:Provides val keyguardViewController: KeyguardViewController = mock(), @get:Provides val dialogLaunchAnimator: DialogLaunchAnimator = mock(), @get:Provides val sysuiState: SysUiState = mock(), // log buffers @get:[Provides BroadcastDispatcherLog] Loading