blob: afcba3bfe3303bed1281d0d02e8e721bf16fedb8 [file] [log] [blame]
Amith Yamasani7805a102014-08-22 09:27:25 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Amith Yamasanic2a8d152014-08-25 14:15:25 -070019import android.app.AlertDialog;
Amith Yamasani7805a102014-08-22 09:27:25 -070020import android.content.Context;
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080021import android.content.pm.UserInfo;
Amith Yamasani7805a102014-08-22 09:27:25 -070022import android.content.res.Resources;
Amith Yamasani5e5cb462015-02-09 15:45:26 -080023import android.os.Handler;
24import android.os.Message;
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080025import android.os.UserHandle;
26import android.os.UserManager;
Amith Yamasanic2a8d152014-08-25 14:15:25 -070027import android.view.LayoutInflater;
28import android.view.View;
Craig Mautner9c795042014-10-28 19:59:59 -070029import android.view.ViewTreeObserver;
Amith Yamasani7805a102014-08-22 09:27:25 -070030import android.view.WindowManager;
Amith Yamasanic2a8d152014-08-25 14:15:25 -070031import android.widget.TextView;
32
33import com.android.internal.R;
Amith Yamasani5e5cb462015-02-09 15:45:26 -080034import com.android.internal.annotations.GuardedBy;
Amith Yamasani7805a102014-08-22 09:27:25 -070035
36/**
37 * Dialog to show when a user switch it about to happen. The intent is to snapshot the screen
38 * immediately after the dialog shows so that the user is informed that something is happening
39 * in the background rather than just freeze the screen and not know if the user-switch affordance
40 * was being handled.
41 */
Craig Mautner9c795042014-10-28 19:59:59 -070042final class UserSwitchingDialog extends AlertDialog
43 implements ViewTreeObserver.OnWindowShownListener {
Amith Yamasani7805a102014-08-22 09:27:25 -070044 private static final String TAG = "ActivityManagerUserSwitchingDialog";
45
Amith Yamasani5e5cb462015-02-09 15:45:26 -080046 // Time to wait for the onWindowShown() callback before continuing the user switch
47 private static final int WINDOW_SHOWN_TIMEOUT_MS = 3000;
48
Amith Yamasani7805a102014-08-22 09:27:25 -070049 private final ActivityManagerService mService;
50 private final int mUserId;
Amith Yamasani5e5cb462015-02-09 15:45:26 -080051 private static final int MSG_START_USER = 1;
52 @GuardedBy("this")
53 private boolean mStartedUser;
Amith Yamasani7805a102014-08-22 09:27:25 -070054
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080055 public UserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
Alex Chau93ae42b2018-01-11 15:10:12 +000056 UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
57 String switchingToSystemUserMessage) {
Amith Yamasani7805a102014-08-22 09:27:25 -070058 super(context);
59
60 mService = service;
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080061 mUserId = newUser.id;
Amith Yamasanic2a8d152014-08-25 14:15:25 -070062
63 // Set up the dialog contents
Amith Yamasani7805a102014-08-22 09:27:25 -070064 setCancelable(false);
Amith Yamasanic2a8d152014-08-25 14:15:25 -070065 Resources res = getContext().getResources();
66 // Custom view due to alignment and font size requirements
67 View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog, null);
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080068
Alex Chau93ae42b2018-01-11 15:10:12 +000069 String viewMessage = null;
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080070 if (UserManager.isSplitSystemUser() && newUser.id == UserHandle.USER_SYSTEM) {
71 viewMessage = res.getString(R.string.user_logging_out_message, oldUser.name);
Suprabh Shuklaff0939b2016-06-01 23:19:06 -070072 } else if (UserManager.isDeviceInDemoMode(context)) {
73 if (oldUser.isDemo()) {
74 viewMessage = res.getString(R.string.demo_restarting_message);
75 } else {
76 viewMessage = res.getString(R.string.demo_starting_message);
77 }
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080078 } else {
Alex Chau93ae42b2018-01-11 15:10:12 +000079 if (oldUser.id == UserHandle.USER_SYSTEM) {
80 viewMessage = switchingFromSystemUserMessage;
81 } else if (newUser.id == UserHandle.USER_SYSTEM) {
82 viewMessage = switchingToSystemUserMessage;
83 }
84
85 // If switchingFromSystemUserMessage or switchingToSystemUserMessage is null, fallback
86 // to system message.
87 if (viewMessage == null) {
88 viewMessage = res.getString(R.string.user_switching_message, newUser.name);
89 }
Suprabh Shukla4fe508b2015-11-20 18:22:57 -080090 }
91 ((TextView) view.findViewById(R.id.message)).setText(viewMessage);
Amith Yamasanic2a8d152014-08-25 14:15:25 -070092 setView(view);
93
Amith Yamasani7805a102014-08-22 09:27:25 -070094 if (aboveSystem) {
95 getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
96 }
97 WindowManager.LayoutParams attrs = getWindow().getAttributes();
98 attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
99 WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
100 getWindow().setAttributes(attrs);
101 }
102
103 @Override
104 public void show() {
Craig Mautner9c795042014-10-28 19:59:59 -0700105 // Slog.v(TAG, "show called");
Amith Yamasani7805a102014-08-22 09:27:25 -0700106 super.show();
Craig Mautner9c795042014-10-28 19:59:59 -0700107 final View decorView = getWindow().getDecorView();
108 if (decorView != null) {
109 decorView.getViewTreeObserver().addOnWindowShownListener(this);
110 }
Amith Yamasani5e5cb462015-02-09 15:45:26 -0800111 // Add a timeout as a safeguard, in case a race in screen on/off causes the window
112 // callback to never come.
113 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER),
114 WINDOW_SHOWN_TIMEOUT_MS);
Amith Yamasani7805a102014-08-22 09:27:25 -0700115 }
116
Craig Mautner9c795042014-10-28 19:59:59 -0700117 @Override
118 public void onWindowShown() {
119 // Slog.v(TAG, "onWindowShown called");
Amith Yamasani5e5cb462015-02-09 15:45:26 -0800120 startUser();
121 }
122
123 void startUser() {
124 synchronized (this) {
125 if (!mStartedUser) {
Evan Rosky18396452016-07-27 15:19:37 -0700126 mService.mUserController.startUserInForeground(mUserId);
127 dismiss();
Amith Yamasani5e5cb462015-02-09 15:45:26 -0800128 mStartedUser = true;
129 final View decorView = getWindow().getDecorView();
130 if (decorView != null) {
131 decorView.getViewTreeObserver().removeOnWindowShownListener(this);
132 }
133 mHandler.removeMessages(MSG_START_USER);
134 }
Amith Yamasani7805a102014-08-22 09:27:25 -0700135 }
Craig Mautner9c795042014-10-28 19:59:59 -0700136 }
Amith Yamasani5e5cb462015-02-09 15:45:26 -0800137
138 private final Handler mHandler = new Handler() {
139 @Override
140 public void handleMessage(Message msg) {
141 switch (msg.what) {
142 case MSG_START_USER:
143 startUser();
144 break;
145 }
146 }
147 };
Amith Yamasani7805a102014-08-22 09:27:25 -0700148}