Merge "Create dialog to show detecting Batmobile device & unlocking" into qt-qpr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
cf885ef399
@@ -21,4 +21,8 @@
|
|||||||
coreApp="true">
|
coreApp="true">
|
||||||
<!-- This permission is required to monitor car power state. -->
|
<!-- This permission is required to monitor car power state. -->
|
||||||
<uses-permission android:name="android.car.permission.CAR_POWER" />
|
<uses-permission android:name="android.car.permission.CAR_POWER" />
|
||||||
|
<!-- This permission is required to get the trusted device list of a user. -->
|
||||||
|
<uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
|
||||||
|
<!-- This permission is required to get bluetooth broadcast. -->
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2019 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
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/unlock_dialog_background_color"/>
|
||||||
|
<padding
|
||||||
|
android:bottom="@*android:dimen/car_padding_2"
|
||||||
|
android:left="@*android:dimen/car_padding_2"
|
||||||
|
android:right="@*android:dimen/car_padding_2"
|
||||||
|
android:top="@*android:dimen/car_padding_2"/>
|
||||||
|
<corners
|
||||||
|
android:radius="@dimen/unlock_dialog_radius"/>
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2019 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
|
||||||
|
-->
|
||||||
|
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="@dimen/unlock_dialog_width"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@drawable/unlock_dialog_background"
|
||||||
|
android:padding="@*android:dimen/car_padding_2">
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<ProgressBar
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_width="@dimen/unlock_dialog_progress_bar_size"
|
||||||
|
android:layout_height="@dimen/unlock_dialog_progress_bar_size" />
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_width="@dimen/unlock_dialog_avatar_size"
|
||||||
|
android:layout_height="@dimen/unlock_dialog_avatar_size"
|
||||||
|
android:scaleType="fitCenter"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/user_name"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:text="@string/unlock_dialog_default_user_name"
|
||||||
|
android:textSize="@*android:dimen/car_body1_size"
|
||||||
|
android:textColor="@android:color/white"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/unlocking_text"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_marginTop="@*android:dimen/car_padding_1"
|
||||||
|
android:text="@string/unlock_dialog_message_default"
|
||||||
|
android:textSize="@*android:dimen/car_body4_size"
|
||||||
|
android:textColor="@color/unlock_dialog_message_text_default"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/enter_pin_button"
|
||||||
|
android:layout_marginTop="@*android:dimen/car_padding_1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:text="@string/unlock_dialog_button_text_pin"
|
||||||
|
style="@style/UnlockDialogButton"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
@@ -26,4 +26,9 @@
|
|||||||
<color name="car_user_switcher_add_user_background_color">@*android:color/car_dark_blue_grey_600</color>
|
<color name="car_user_switcher_add_user_background_color">@*android:color/car_dark_blue_grey_600</color>
|
||||||
<color name="car_user_switcher_add_user_add_sign_color">@*android:color/car_body1_light</color>
|
<color name="car_user_switcher_add_user_add_sign_color">@*android:color/car_body1_light</color>
|
||||||
|
|
||||||
|
<!-- colors for unlock dialog -->
|
||||||
|
<color name="unlock_dialog_background_color">#ff282a2d</color>
|
||||||
|
<color name="unlock_dialog_message_text_default">@*android:color/car_grey_400</color>
|
||||||
|
<color name="unlock_dialog_enter_pin_text_color">#ff66b5ff</color>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -43,4 +43,10 @@
|
|||||||
<!-- This must be the negative of car_user_switcher_container_height for the animation. -->
|
<!-- This must be the negative of car_user_switcher_container_height for the animation. -->
|
||||||
<dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
|
<dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
|
||||||
|
|
||||||
|
<!-- dimensions for the unlock dialog -->
|
||||||
|
<dimen name="unlock_dialog_width">500dp</dimen>
|
||||||
|
<dimen name="unlock_dialog_radius">16dp</dimen>
|
||||||
|
<dimen name="unlock_dialog_avatar_size">100dp</dimen>
|
||||||
|
<dimen name="unlock_dialog_progress_bar_size">140dp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -31,5 +31,7 @@
|
|||||||
<!--Percentage of the screen height, from the bottom, that a notification panel being peeked
|
<!--Percentage of the screen height, from the bottom, that a notification panel being peeked
|
||||||
at will result in remaining closed the panel if released-->
|
at will result in remaining closed the panel if released-->
|
||||||
<integer name="notification_settle_close_percentage">80</integer>
|
<integer name="notification_settle_close_percentage">80</integer>
|
||||||
|
<!-- The delay before the unlock dialog pops up -->
|
||||||
|
<integer name="unlock_dialog_delay_ms">3000</integer>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -29,4 +29,19 @@
|
|||||||
<string name="user_add_user_message_setup">When you add a new user, that person needs to set up their space.</string>
|
<string name="user_add_user_message_setup">When you add a new user, that person needs to set up their space.</string>
|
||||||
<!-- Message to inform user that the newly created user will have permissions to update apps for all other users. [CHAR LIMIT=100] -->
|
<!-- Message to inform user that the newly created user will have permissions to update apps for all other users. [CHAR LIMIT=100] -->
|
||||||
<string name="user_add_user_message_update">Any user can update apps for all other users.</string>
|
<string name="user_add_user_message_update">Any user can update apps for all other users.</string>
|
||||||
|
<!-- Default messages displayed on the unlock dialog before unlock advertising started. [CHAR LIMIT=30]-->
|
||||||
|
<string name="unlock_dialog_message_default">Waiting\u2026</string>
|
||||||
|
<!-- Message to inform user that the IHU is looking for trusted device. [CHAR LIMIT=30] -->
|
||||||
|
<string name="unlock_dialog_message_start">Looking for trusted device\u2026</string>
|
||||||
|
|
||||||
|
<!-- Cancel Button text for user who has PIN as security lock. [CHAR LIMIT=30] -->
|
||||||
|
<string name="unlock_dialog_button_text_pin">Enter PIN instead</string>
|
||||||
|
<!-- Cancel Button text for user who has Pattern as security lock. [CHAR LIMIT=30] -->
|
||||||
|
<string name="unlock_dialog_button_text_pattern">Enter Pattern instead</string>
|
||||||
|
<!-- Cancel Button text for user who has Password as security lock. [CHAR LIMIT=30] -->
|
||||||
|
<string name="unlock_dialog_button_text_password">Enter Password instead</string>
|
||||||
|
<!-- Default user name shows on unlock dialog -->
|
||||||
|
<string name="unlock_dialog_default_user_name">Default Name</string>
|
||||||
|
<!-- Default title for unlock dialog -->
|
||||||
|
<string name="unlock_dialog_title">Unlock Dialogue</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -46,4 +46,12 @@
|
|||||||
<item name="android:layout_width">96dp</item>
|
<item name="android:layout_width">96dp</item>
|
||||||
<item name="android:background">@drawable/nav_button_background</item>
|
<item name="android:background">@drawable/nav_button_background</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="UnlockDialogButton">
|
||||||
|
<item name="android:background">?android:attr/selectableItemBackground</item>
|
||||||
|
<item name="android:textAlignment">center</item>
|
||||||
|
<item name="android:textColor">@color/unlock_dialog_enter_pin_text_color</item>
|
||||||
|
<item name="android:paddingHorizontal">16dp</item>
|
||||||
|
<item name="android:textAllCaps">false</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -26,6 +26,7 @@ import android.car.Car;
|
|||||||
import android.car.drivingstate.CarDrivingStateEvent;
|
import android.car.drivingstate.CarDrivingStateEvent;
|
||||||
import android.car.drivingstate.CarUxRestrictionsManager;
|
import android.car.drivingstate.CarUxRestrictionsManager;
|
||||||
import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
|
import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
|
||||||
|
import android.car.trust.CarTrustAgentEnrollmentManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -1027,8 +1028,12 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
UserSwitcherController userSwitcherController =
|
UserSwitcherController userSwitcherController =
|
||||||
Dependency.get(UserSwitcherController.class);
|
Dependency.get(UserSwitcherController.class);
|
||||||
if (userSwitcherController.useFullscreenUserSwitcher()) {
|
if (userSwitcherController.useFullscreenUserSwitcher()) {
|
||||||
|
Car car = Car.createCar(mContext);
|
||||||
|
CarTrustAgentEnrollmentManager enrollmentManager = (CarTrustAgentEnrollmentManager) car
|
||||||
|
.getCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE);
|
||||||
mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
|
mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
|
||||||
mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
|
mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub),
|
||||||
|
enrollmentManager, mContext);
|
||||||
} else {
|
} else {
|
||||||
super.createUserSwitcher();
|
super.createUserSwitcher();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 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.statusbar.car;
|
||||||
|
|
||||||
|
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.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class displays an unlock dialog and receives broadcast about detecting trusted device
|
||||||
|
* & unlocking state to show the appropriate message on the dialog.
|
||||||
|
*/
|
||||||
|
class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{
|
||||||
|
private static final String TAG = CarTrustAgentUnlockDialogHelper.class.getSimpleName();
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final WindowManager mWindowManager;
|
||||||
|
private final UserManager mUserManager;
|
||||||
|
private final WindowManager.LayoutParams mParams;
|
||||||
|
/**
|
||||||
|
* Not using Dialog because context passed from {@link FullscreenUserSwitcher} is not an
|
||||||
|
* activity.
|
||||||
|
*/
|
||||||
|
private final View mUnlockDialog;
|
||||||
|
private final TextView mUnlockingText;
|
||||||
|
private final Button mButton;
|
||||||
|
private final IntentFilter mFilter;
|
||||||
|
private int mUid;
|
||||||
|
private boolean mIsDialogShowing;
|
||||||
|
private OnHideListener mOnHideListener;
|
||||||
|
|
||||||
|
CarTrustAgentUnlockDialogHelper(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mUserManager = mContext.getSystemService(UserManager.class);
|
||||||
|
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||||
|
mParams = createLayoutParams();
|
||||||
|
mFilter = getIntentFilter();
|
||||||
|
|
||||||
|
mParams.packageName = mContext.getPackageName();
|
||||||
|
mParams.setTitle(mContext.getString(R.string.unlock_dialog_title));
|
||||||
|
|
||||||
|
mUnlockDialog = LayoutInflater.from(mContext).inflate(
|
||||||
|
R.layout.trust_agent_unlock_dialog, null);
|
||||||
|
mUnlockDialog.setLayoutParams(mParams);
|
||||||
|
|
||||||
|
mUnlockingText = mUnlockDialog.findViewById(R.id.unlocking_text);
|
||||||
|
mButton = mUnlockDialog.findViewById(R.id.enter_pin_button);
|
||||||
|
mButton.setOnClickListener(v -> {
|
||||||
|
hideUnlockDialog(/* notifyOnHideListener= */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 = mContext.getResources().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(mUnlockDialog, mParams);
|
||||||
|
}
|
||||||
|
}, delayMillis);
|
||||||
|
}
|
||||||
|
mIsDialogShowing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUid(int uid) {
|
||||||
|
mUid = uid;
|
||||||
|
TextView userName = mUnlockDialog.findViewById(R.id.user_name);
|
||||||
|
userName.setText(mUserManager.getUserInfo(mUid).name);
|
||||||
|
ImageView avatar = mUnlockDialog.findViewById(R.id.avatar);
|
||||||
|
avatar.setImageBitmap(mUserManager.getUserIcon(mUid));
|
||||||
|
setButtonText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideUnlockDialog(boolean notifyOnHideListener) {
|
||||||
|
if (!mIsDialogShowing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mWindowManager.removeView(mUnlockDialog);
|
||||||
|
logd("Receiver unregistered");
|
||||||
|
mContext.unregisterReceiver(this);
|
||||||
|
if (notifyOnHideListener && mOnHideListener != null) {
|
||||||
|
mOnHideListener.onHide();
|
||||||
|
}
|
||||||
|
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 security lock type
|
||||||
|
private void setButtonText() {
|
||||||
|
LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
|
||||||
|
int passwordQuality = lockPatternUtils.getActivePasswordQuality(mUid);
|
||||||
|
switch (passwordQuality) {
|
||||||
|
// PIN
|
||||||
|
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||||
|
// Pattern
|
||||||
|
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||||
|
mButton.setText(R.string.unlock_dialog_button_text_pattern);
|
||||||
|
break;
|
||||||
|
// Password
|
||||||
|
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
|
||||||
|
mButton.setText(R.string.unlock_dialog_button_text_password);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Encountered unexpected security type when attempting to set "
|
||||||
|
+ "button text:" + passwordQuality);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WindowManager.LayoutParams createLayoutParams() {
|
||||||
|
return 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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,29 +18,60 @@ package com.android.systemui.statusbar.car;
|
|||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.car.trust.CarTrustAgentEnrollmentManager;
|
||||||
|
import android.car.userlib.CarUserManagerHelper;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewStub;
|
import android.view.ViewStub;
|
||||||
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the fullscreen user switcher.
|
* Manages the fullscreen user switcher.
|
||||||
*/
|
*/
|
||||||
public class FullscreenUserSwitcher {
|
public class FullscreenUserSwitcher {
|
||||||
|
private static final String TAG = FullscreenUserSwitcher.class.getSimpleName();
|
||||||
|
// Because user 0 is headless, user count for single user is 2
|
||||||
|
private static final int NUMBER_OF_BACKGROUND_USERS = 1;
|
||||||
private final UserGridRecyclerView mUserGridView;
|
private final UserGridRecyclerView mUserGridView;
|
||||||
private final View mParent;
|
private final View mParent;
|
||||||
private final int mShortAnimDuration;
|
private final int mShortAnimDuration;
|
||||||
private final CarStatusBar mStatusBar;
|
private final CarStatusBar mStatusBar;
|
||||||
|
private final Context mContext;
|
||||||
|
private final UserManager mUserManager;
|
||||||
|
private final CarTrustAgentEnrollmentManager mEnrollmentManager;
|
||||||
|
private CarTrustAgentUnlockDialogHelper mUnlockDialogHelper;
|
||||||
|
private UserGridRecyclerView.UserRecord mSelectedUser;
|
||||||
|
private CarUserManagerHelper mCarUserManagerHelper;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub, Context context) {
|
|
||||||
|
public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub,
|
||||||
|
CarTrustAgentEnrollmentManager enrollmentManager, Context context) {
|
||||||
mStatusBar = statusBar;
|
mStatusBar = statusBar;
|
||||||
mParent = containerStub.inflate();
|
mParent = containerStub.inflate();
|
||||||
// Hide the user grid by default. It will only be made visible by clicking on a cancel
|
mEnrollmentManager = enrollmentManager;
|
||||||
// button in a bouncer.
|
mContext = context;
|
||||||
hide();
|
|
||||||
View container = mParent.findViewById(R.id.container);
|
View container = mParent.findViewById(R.id.container);
|
||||||
|
|
||||||
// Initialize user grid.
|
// Initialize user grid.
|
||||||
@@ -50,9 +81,51 @@ public class FullscreenUserSwitcher {
|
|||||||
mUserGridView.setLayoutManager(layoutManager);
|
mUserGridView.setLayoutManager(layoutManager);
|
||||||
mUserGridView.buildAdapter();
|
mUserGridView.buildAdapter();
|
||||||
mUserGridView.setUserSelectionListener(this::onUserSelected);
|
mUserGridView.setUserSelectionListener(this::onUserSelected);
|
||||||
|
mCarUserManagerHelper = new CarUserManagerHelper(context);
|
||||||
|
mUnlockDialogHelper = new CarTrustAgentUnlockDialogHelper(mContext);
|
||||||
|
mUserManager = mContext.getSystemService(UserManager.class);
|
||||||
|
|
||||||
mShortAnimDuration = container.getResources()
|
mShortAnimDuration = container.getResources()
|
||||||
.getInteger(android.R.integer.config_shortAnimTime);
|
.getInteger(android.R.integer.config_shortAnimTime);
|
||||||
|
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
|
||||||
|
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),
|
||||||
|
filter,
|
||||||
|
/* broadcastPermission= */ null,
|
||||||
|
/* scheduler */ null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDialogForInitialUser() {
|
||||||
|
int initialUser = mCarUserManagerHelper.getInitialUser();
|
||||||
|
UserInfo initialUserInfo = mUserManager.getUserInfo(initialUser);
|
||||||
|
mSelectedUser = new UserRecord(initialUserInfo,
|
||||||
|
/* isStartGuestSession= */ false,
|
||||||
|
/* isAddUser= */ false,
|
||||||
|
/* isForeground= */ true);
|
||||||
|
// For single user without trusted device, hide the user switcher.
|
||||||
|
if (!hasMultipleUsers() && !hasTrustedDevice(initialUser)) {
|
||||||
|
dismissUserSwitcher();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Show unlock dialog for initial user
|
||||||
|
if (hasTrustedDevice(initialUser)) {
|
||||||
|
mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
|
||||||
|
() -> dismissUserSwitcher());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if there is only one possible user to login in.
|
||||||
|
* In a Multi-User system there is always one background user (user 0)
|
||||||
|
*/
|
||||||
|
private boolean hasMultipleUsers() {
|
||||||
|
return mUserManager.getUserCount() > NUMBER_OF_BACKGROUND_USERS + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,14 +150,33 @@ public class FullscreenUserSwitcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Every time user clicks on an item in the switcher, we hide the switcher, either
|
* Every time user clicks on an item in the switcher, if the clicked user has no trusted device,
|
||||||
* gradually or immediately.
|
* we hide the switcher, either gradually or immediately.
|
||||||
*
|
*
|
||||||
* We dismiss the entire keyguard if user clicked on the foreground user (user we're already
|
* If the user has trusted device, we show an unlock dialog to notify user the unlock state.
|
||||||
* logged in as).
|
* 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).
|
||||||
*/
|
*/
|
||||||
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
|
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
|
||||||
if (record.mIsForeground) {
|
mSelectedUser = record;
|
||||||
|
if (hasTrustedDevice(record.mInfo.id)) {
|
||||||
|
mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, () -> dismissUserSwitcher());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||||
|
Log.d(TAG, "no trusted device enrolled for uid: " + record.mInfo.id);
|
||||||
|
}
|
||||||
|
dismissUserSwitcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dismissUserSwitcher() {
|
||||||
|
if (mSelectedUser == null) {
|
||||||
|
Log.e(TAG, "Request to dismiss user switcher, but no user selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mSelectedUser.mIsForeground) {
|
||||||
hide();
|
hide();
|
||||||
mStatusBar.dismissKeyguard();
|
mStatusBar.dismissKeyguard();
|
||||||
return;
|
return;
|
||||||
@@ -106,4 +198,8 @@ public class FullscreenUserSwitcher {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasTrustedDevice(int uid) {
|
||||||
|
return !mEnrollmentManager.getEnrolledDeviceInfoForUser(uid).isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user