Merge "Remove unlock dialog from sysui" into rvc-dev
This commit is contained in:
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.car.userswitcher;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* A helper class displays an unlock dialog and receives broadcast about detecting trusted device
|
||||
* & unlocking state to show the appropriate message on the dialog.
|
||||
*/
|
||||
@Singleton
|
||||
class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{
|
||||
private static final String TAG = CarTrustAgentUnlockDialogHelper.class.getSimpleName();
|
||||
|
||||
private final Context mContext;
|
||||
private final Resources mResources;
|
||||
private final WindowManager mWindowManager;
|
||||
private final UserManager mUserManager;
|
||||
private final WindowManager.LayoutParams mParams;
|
||||
/**
|
||||
* Not using Dialog because context passed from {@link FullscreenUserSwitcherViewMediator}
|
||||
* is not an activity.
|
||||
*/
|
||||
private final View mUnlockDialogLayout;
|
||||
private final TextView mUnlockingText;
|
||||
private final Button mButton;
|
||||
private final IntentFilter mFilter;
|
||||
private int mUid;
|
||||
private boolean mIsDialogShowing;
|
||||
private OnHideListener mOnHideListener;
|
||||
|
||||
@Inject
|
||||
CarTrustAgentUnlockDialogHelper(Context context, @Main Resources resources,
|
||||
UserManager userManager, WindowManager windowManager) {
|
||||
mContext = context;
|
||||
mResources = resources;
|
||||
mUserManager = userManager;
|
||||
mWindowManager = windowManager;
|
||||
mParams = createLayoutParams();
|
||||
mFilter = getIntentFilter();
|
||||
|
||||
mParams.packageName = mContext.getPackageName();
|
||||
mParams.setTitle(mContext.getString(R.string.unlock_dialog_title));
|
||||
|
||||
mUnlockDialogLayout = LayoutInflater.from(mContext).inflate(
|
||||
R.layout.trust_agent_unlock_dialog, null);
|
||||
mUnlockDialogLayout.setLayoutParams(mParams);
|
||||
|
||||
View dialogParent = mUnlockDialogLayout.findViewById(R.id.unlock_dialog_parent);
|
||||
dialogParent.setOnTouchListener((v, event)-> {
|
||||
hideUnlockDialog(/* dismissUserSwitcher= */ false);
|
||||
return true;
|
||||
});
|
||||
View unlockDialog = mUnlockDialogLayout.findViewById(R.id.unlock_dialog);
|
||||
unlockDialog.setOnTouchListener((v, event) -> {
|
||||
// If the person taps inside the unlock dialog, the touch event will be intercepted here
|
||||
// and the dialog will not exit
|
||||
return true;
|
||||
});
|
||||
mUnlockingText = mUnlockDialogLayout.findViewById(R.id.unlocking_text);
|
||||
mButton = mUnlockDialogLayout.findViewById(R.id.enter_pin_button);
|
||||
mButton.setOnClickListener(v -> {
|
||||
hideUnlockDialog(/* dismissUserSwitcher= */true);
|
||||
// TODO(b/138250105) Stop unlock advertising
|
||||
});
|
||||
|
||||
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (bluetoothAdapter != null
|
||||
&& bluetoothAdapter.getLeState() == BluetoothAdapter.STATE_BLE_ON) {
|
||||
mUnlockingText.setText(R.string.unlock_dialog_message_start);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This filter is listening on:
|
||||
* {@link BluetoothAdapter#ACTION_BLE_STATE_CHANGED} for starting unlock advertising;
|
||||
* {@link Intent#ACTION_USER_UNLOCKED} for IHU unlocked
|
||||
*/
|
||||
private IntentFilter getIntentFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
|
||||
filter.addAction(Intent.ACTION_USER_UNLOCKED);
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show dialog for the given user
|
||||
*/
|
||||
void showUnlockDialog(int uid, OnHideListener listener) {
|
||||
showUnlockDialogAfterDelay(uid, 0, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show dialog for the given user after the certain time of delay has elapsed
|
||||
*
|
||||
* @param uid the user to unlock
|
||||
* @param listener listener that listens to dialog hide
|
||||
*/
|
||||
void showUnlockDialogAfterDelay(int uid, OnHideListener listener) {
|
||||
long delayMillis = mResources.getInteger(R.integer.unlock_dialog_delay_ms);
|
||||
showUnlockDialogAfterDelay(uid, delayMillis, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show dialog for the given user after the supplied delay has elapsed
|
||||
*/
|
||||
private void showUnlockDialogAfterDelay(int uid, long delayMillis, OnHideListener listener) {
|
||||
setUid(uid);
|
||||
mOnHideListener = listener;
|
||||
if (!mIsDialogShowing) {
|
||||
logd("Receiver registered");
|
||||
mContext.registerReceiverAsUser(this, UserHandle.ALL, mFilter,
|
||||
/* broadcastPermission= */ null,
|
||||
/* scheduler= */ null);
|
||||
new Handler().postDelayed(() -> {
|
||||
if (!mUserManager.isUserUnlocked(uid)) {
|
||||
logd("Showed unlock dialog for user: " + uid + " after " + delayMillis
|
||||
+ " delay.");
|
||||
mWindowManager.addView(mUnlockDialogLayout, mParams);
|
||||
}
|
||||
}, delayMillis);
|
||||
}
|
||||
mIsDialogShowing = true;
|
||||
}
|
||||
|
||||
private void setUid(int uid) {
|
||||
mUid = uid;
|
||||
TextView userName = mUnlockDialogLayout.findViewById(R.id.user_name);
|
||||
userName.setText(mUserManager.getUserInfo(mUid).name);
|
||||
ImageView avatar = mUnlockDialogLayout.findViewById(R.id.avatar);
|
||||
avatar.setImageBitmap(mUserManager.getUserIcon(mUid));
|
||||
setButtonText();
|
||||
}
|
||||
|
||||
private void hideUnlockDialog(boolean dismissUserSwitcher) {
|
||||
if (!mIsDialogShowing) {
|
||||
return;
|
||||
}
|
||||
mWindowManager.removeView(mUnlockDialogLayout);
|
||||
logd("Receiver unregistered");
|
||||
mContext.unregisterReceiver(this);
|
||||
if (mOnHideListener != null) {
|
||||
mOnHideListener.onHide(dismissUserSwitcher);
|
||||
}
|
||||
mIsDialogShowing = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action == null) {
|
||||
return;
|
||||
}
|
||||
switch (action) {
|
||||
case BluetoothAdapter.ACTION_BLE_STATE_CHANGED:
|
||||
logd("Received ACTION_BLE_STATE_CHANGED");
|
||||
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
|
||||
if (state == BluetoothAdapter.STATE_BLE_ON) {
|
||||
logd("Received BLE_ON");
|
||||
mUnlockingText.setText(R.string.unlock_dialog_message_start);
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_USER_UNLOCKED:
|
||||
int uid = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
|
||||
if (uid == mUid) {
|
||||
logd("IHU unlocked");
|
||||
hideUnlockDialog(/* notifyOnHideListener= */false);
|
||||
} else {
|
||||
Log.e(TAG, "Received ACTION_USER_UNLOCKED for unexpected uid: " + uid);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Encountered unexpected action when attempting to set "
|
||||
+ "unlock state message: " + action);
|
||||
}
|
||||
}
|
||||
|
||||
// Set button text based on screen lock type
|
||||
private void setButtonText() {
|
||||
LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
|
||||
int passwordQuality = lockPatternUtils.getActivePasswordQuality(mUid);
|
||||
switch (passwordQuality) {
|
||||
// PIN
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
mButton.setText(R.string.unlock_dialog_button_text_pin);
|
||||
break;
|
||||
// Pattern
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||
mButton.setText(R.string.unlock_dialog_button_text_pattern);
|
||||
break;
|
||||
// Password
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
|
||||
mButton.setText(R.string.unlock_dialog_button_text_password);
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Encountered unexpected screen lock type when attempting to set "
|
||||
+ "button text:" + passwordQuality);
|
||||
}
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams createLayoutParams() {
|
||||
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
|
||||
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
|
||||
PixelFormat.TRANSLUCENT
|
||||
);
|
||||
attrs.setFitInsetsTypes(0 /* types */);
|
||||
return attrs;
|
||||
}
|
||||
|
||||
private void logd(String message) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener used to notify when the dialog is hidden
|
||||
*/
|
||||
interface OnHideListener {
|
||||
void onHide(boolean dismissUserSwitcher);
|
||||
}
|
||||
}
|
||||
@@ -16,23 +16,14 @@
|
||||
|
||||
package com.android.systemui.car.userswitcher;
|
||||
|
||||
import android.car.Car;
|
||||
import android.car.trust.CarTrustAgentEnrollmentManager;
|
||||
import android.car.userlib.CarUserManagerHelper;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.car.CarServiceProvider;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.keyguard.ScreenLifecycle;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
@@ -52,9 +43,6 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
||||
private static final String TAG = FullscreenUserSwitcherViewMediator.class.getSimpleName();
|
||||
|
||||
private final Context mContext;
|
||||
private final UserManager mUserManager;
|
||||
private final CarServiceProvider mCarServiceProvider;
|
||||
private final CarTrustAgentUnlockDialogHelper mUnlockDialogHelper;
|
||||
private final CarStatusBarKeyguardViewManager mCarStatusBarKeyguardViewManager;
|
||||
private final Handler mMainHandler;
|
||||
private final StatusBarStateController mStatusBarStateController;
|
||||
@@ -62,39 +50,12 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
||||
private final ScreenLifecycle mScreenLifecycle;
|
||||
private final CarStatusBar mCarStatusBar;
|
||||
private final boolean mIsUserSwitcherEnabled;
|
||||
private final CarUserManagerHelper mCarUserManagerHelper;
|
||||
|
||||
private CarTrustAgentEnrollmentManager mEnrollmentManager;
|
||||
private UserGridRecyclerView.UserRecord mSelectedUser;
|
||||
private final CarTrustAgentUnlockDialogHelper.OnHideListener mOnHideListener =
|
||||
dismissUserSwitcher -> {
|
||||
if (dismissUserSwitcher) {
|
||||
dismissUserSwitcher();
|
||||
} else {
|
||||
// Re-draw the parent view, otherwise the unlock dialog will not be removed
|
||||
// from the screen immediately.
|
||||
invalidateFullscreenUserSwitcherView();
|
||||
}
|
||||
};
|
||||
private final BroadcastReceiver mUserUnlockReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "user 0 is unlocked, SharedPreference is accessible.");
|
||||
}
|
||||
showDialogForInitialUser();
|
||||
mContext.unregisterReceiver(mUserUnlockReceiver);
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public FullscreenUserSwitcherViewMediator(
|
||||
Context context,
|
||||
@Main Resources resources,
|
||||
@Main Handler mainHandler,
|
||||
UserManager userManager,
|
||||
CarServiceProvider carServiceProvider,
|
||||
CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper,
|
||||
CarStatusBarKeyguardViewManager carStatusBarKeyguardViewManager,
|
||||
CarStatusBar carStatusBar,
|
||||
StatusBarStateController statusBarStateController,
|
||||
@@ -105,21 +66,12 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
||||
mIsUserSwitcherEnabled = resources.getBoolean(R.bool.config_enableFullscreenUserSwitcher);
|
||||
|
||||
mMainHandler = mainHandler;
|
||||
mUserManager = userManager;
|
||||
|
||||
mCarServiceProvider = carServiceProvider;
|
||||
mCarServiceProvider.addListener(
|
||||
car -> mEnrollmentManager = (CarTrustAgentEnrollmentManager) car.getCarManager(
|
||||
Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE));
|
||||
|
||||
mUnlockDialogHelper = carTrustAgentUnlockDialogHelper;
|
||||
mCarStatusBarKeyguardViewManager = carStatusBarKeyguardViewManager;
|
||||
mCarStatusBar = carStatusBar;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mFullScreenUserSwitcherViewController = fullScreenUserSwitcherViewController;
|
||||
mScreenLifecycle = screenLifecycle;
|
||||
|
||||
mCarUserManagerHelper = new CarUserManagerHelper(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,18 +79,6 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
||||
registerUserSwitcherShowListeners();
|
||||
registerUserSwitcherHideListeners();
|
||||
registerHideKeyguardListeners();
|
||||
|
||||
if (mUserManager.isUserUnlocked(UserHandle.USER_SYSTEM)) {
|
||||
// User0 is unlocked, switched to the initial user
|
||||
showDialogForInitialUser();
|
||||
} else {
|
||||
// listen to USER_UNLOCKED
|
||||
mContext.registerReceiverAsUser(mUserUnlockReceiver,
|
||||
UserHandle.getUserHandleForUid(UserHandle.USER_SYSTEM),
|
||||
new IntentFilter(Intent.ACTION_USER_UNLOCKED),
|
||||
/* broadcastPermission= */ null,
|
||||
/* scheduler= */ null);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerUserSwitcherShowListeners() {
|
||||
@@ -194,26 +134,16 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Every time user clicks on an item in the switcher, if the clicked user has no trusted
|
||||
* device, we hide the switcher, either gradually or immediately.
|
||||
* If the user has trusted device, we show an unlock dialog to notify user the unlock
|
||||
* state.
|
||||
* When the unlock dialog is dismissed by user, we hide the unlock dialog and the switcher.
|
||||
* We dismiss the entire keyguard when we hide the switcher if user clicked on the
|
||||
* foreground user (user we're already logged in as).
|
||||
* Every time user clicks on an item in the switcher, we hide the switcher.
|
||||
*
|
||||
* We dismiss the entire keyguard if user clicked on the foreground user (user we're already
|
||||
* logged in as).
|
||||
*/
|
||||
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
|
||||
mSelectedUser = record;
|
||||
if (record.mInfo != null) {
|
||||
if (hasScreenLock(record.mInfo.id) && hasTrustedDevice(record.mInfo.id)) {
|
||||
mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, mOnHideListener);
|
||||
return;
|
||||
}
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "no trusted device enrolled for uid: " + record.mInfo.id);
|
||||
}
|
||||
hide();
|
||||
if (record.mType == UserGridRecyclerView.UserRecord.FOREGROUND_USER) {
|
||||
mCarStatusBar.dismissKeyguard();
|
||||
}
|
||||
dismissUserSwitcher();
|
||||
}
|
||||
|
||||
// We automatically dismiss keyguard unless user switcher is being shown above the keyguard.
|
||||
@@ -234,53 +164,6 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasScreenLock(int uid) {
|
||||
LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
|
||||
return lockPatternUtils.getCredentialTypeForUser(uid)
|
||||
!= LockPatternUtils.CREDENTIAL_TYPE_NONE;
|
||||
}
|
||||
|
||||
private boolean hasTrustedDevice(int uid) {
|
||||
if (mEnrollmentManager == null) { // car service not ready, so it cannot be available.
|
||||
return false;
|
||||
}
|
||||
return !mEnrollmentManager.getEnrolledDeviceInfoForUser(uid).isEmpty();
|
||||
}
|
||||
|
||||
private void dismissUserSwitcher() {
|
||||
if (mSelectedUser == null) {
|
||||
Log.e(TAG, "Request to dismiss user switcher, but no user selected");
|
||||
return;
|
||||
}
|
||||
if (mSelectedUser.mType == UserGridRecyclerView.UserRecord.FOREGROUND_USER) {
|
||||
hide();
|
||||
mCarStatusBar.dismissKeyguard();
|
||||
return;
|
||||
}
|
||||
hide();
|
||||
}
|
||||
|
||||
private void showDialogForInitialUser() {
|
||||
int initialUser = mCarUserManagerHelper.getInitialUser();
|
||||
UserInfo initialUserInfo = mUserManager.getUserInfo(initialUser);
|
||||
mSelectedUser = new UserGridRecyclerView.UserRecord(initialUserInfo,
|
||||
UserGridRecyclerView.UserRecord.FOREGROUND_USER);
|
||||
|
||||
// If the initial user has screen lock and trusted device, display the unlock dialog on the
|
||||
// keyguard.
|
||||
if (hasScreenLock(initialUser) && hasTrustedDevice(initialUser)) {
|
||||
mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
|
||||
mOnHideListener);
|
||||
} else {
|
||||
// If no trusted device, dismiss the keyguard.
|
||||
dismissUserSwitcher();
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateFullscreenUserSwitcherView() {
|
||||
mFullScreenUserSwitcherViewController.invalidate();
|
||||
}
|
||||
|
||||
private void hide() {
|
||||
mFullScreenUserSwitcherViewController.stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user