Merge "Implement UserSwitchingDialog in SystemUI mounted to OverlayWindow." into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
81eefd515f
@@ -1,37 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2018 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.
|
|
||||||
-->
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/user_loading_avatar"
|
|
||||||
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
|
|
||||||
android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
|
|
||||||
android:layout_centerHorizontal="true"/>
|
|
||||||
|
|
||||||
<TextView android:id="@+id/user_loading"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/car_padding_4"
|
|
||||||
android:textSize="@dimen/car_body1_size"
|
|
||||||
android:textColor="@color/car_body1"
|
|
||||||
android:layout_below="@id/user_loading_avatar"
|
|
||||||
android:gravity="center"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
@@ -16,14 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
|
|
||||||
<dimen name="car_fullscreen_user_pod_width">243dp</dimen>
|
|
||||||
<dimen name="car_fullscreen_user_pod_height">356dp</dimen>
|
|
||||||
<dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
|
|
||||||
<dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
|
|
||||||
<dimen name="car_large_avatar_size">96dp</dimen>
|
<dimen name="car_large_avatar_size">96dp</dimen>
|
||||||
|
|
||||||
|
|
||||||
<!-- Application Bar -->
|
<!-- Application Bar -->
|
||||||
<dimen name="car_app_bar_height">80dp</dimen>
|
<dimen name="car_app_bar_height">80dp</dimen>
|
||||||
<!-- Margin -->
|
<!-- Margin -->
|
||||||
|
|||||||
@@ -3641,13 +3641,6 @@
|
|||||||
<java-symbol type="color" name="car_card_dark" />
|
<java-symbol type="color" name="car_card_dark" />
|
||||||
<java-symbol type="dimen" name="car_body1_size" />
|
<java-symbol type="dimen" name="car_body1_size" />
|
||||||
<java-symbol type="dimen" name="car_padding_4" />
|
<java-symbol type="dimen" name="car_padding_4" />
|
||||||
<java-symbol type="dimen" name="car_fullscreen_user_pod_icon_text_size" />
|
|
||||||
<java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_height" />
|
|
||||||
<java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_width" />
|
|
||||||
<java-symbol type="dimen" name="car_large_avatar_size" />
|
|
||||||
<java-symbol type="layout" name="car_user_switching_dialog" />
|
|
||||||
<java-symbol type="id" name="user_loading_avatar" />
|
|
||||||
<java-symbol type="id" name="user_loading" />
|
|
||||||
<java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" />
|
<java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" />
|
||||||
|
|
||||||
<java-symbol type="string" name="battery_saver_description_with_learn_more" />
|
<java-symbol type="string" name="battery_saver_description_with_learn_more" />
|
||||||
|
|||||||
@@ -25,4 +25,6 @@
|
|||||||
<uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
|
<uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
|
||||||
<!-- This permission is required to get bluetooth broadcast. -->
|
<!-- This permission is required to get bluetooth broadcast. -->
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<!-- This permission is required to check the foreground user id. -->
|
||||||
|
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@color/car_user_switching_dialog_background_color">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center_horizontal">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/user_loading_avatar"
|
||||||
|
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
|
||||||
|
android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/user_loading"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/car_user_switching_dialog_loading_text_margin_top"
|
||||||
|
android:textSize="@dimen/car_user_switching_dialog_loading_text_font_size"
|
||||||
|
android:textColor="@color/car_user_switching_dialog_loading_text_color"
|
||||||
|
android:layout_below="@id/user_loading_avatar"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
@@ -39,4 +39,9 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout="@layout/car_fullscreen_user_switcher"/>
|
android:layout="@layout/car_fullscreen_user_switcher"/>
|
||||||
|
|
||||||
|
<ViewStub android:id="@+id/user_switching_dialog_stub"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout="@layout/car_user_switching_dialog"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
@@ -55,4 +55,7 @@
|
|||||||
<color name="list_divider_color">@*android:color/car_list_divider_light</color>
|
<color name="list_divider_color">@*android:color/car_list_divider_light</color>
|
||||||
<color name="car_volume_item_divider_color">@*android:color/car_list_divider</color>
|
<color name="car_volume_item_divider_color">@*android:color/car_list_divider</color>
|
||||||
<color name="car_volume_item_background_color">@*android:color/car_card_dark</color>
|
<color name="car_volume_item_background_color">@*android:color/car_card_dark</color>
|
||||||
|
|
||||||
|
<color name="car_user_switching_dialog_background_color">@android:color/black</color>
|
||||||
|
<color name="car_user_switching_dialog_loading_text_color">@*android:color/car_body1</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -70,11 +70,13 @@
|
|||||||
to a constant alpha percent value using the initial alpha. -->
|
to a constant alpha percent value using the initial alpha. -->
|
||||||
<integer name="config_finalNotificationBackgroundAlpha">100</integer>
|
<integer name="config_finalNotificationBackgroundAlpha">100</integer>
|
||||||
|
|
||||||
<!-- Car System UI's OverlayViewsMediator-->
|
<!-- Car System UI's OverlayViewsMediator.
|
||||||
|
Whenever a new class is added, make sure to also add that class to OverlayWindowModule. -->
|
||||||
<string-array name="config_carSystemUIOverlayViewsMediators" translatable="false">
|
<string-array name="config_carSystemUIOverlayViewsMediators" translatable="false">
|
||||||
<item>@string/config_notificationPanelViewMediator</item>
|
<item>@string/config_notificationPanelViewMediator</item>
|
||||||
<item>com.android.systemui.car.keyguard.CarKeyguardViewMediator</item>
|
<item>com.android.systemui.car.keyguard.CarKeyguardViewMediator</item>
|
||||||
<item>com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator</item>
|
<item>com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator</item>
|
||||||
|
<item>com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
@@ -15,6 +15,32 @@
|
|||||||
~ limitations under the License
|
~ limitations under the License
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- Text size for car -->
|
||||||
|
<dimen name="car_title_size">32sp</dimen>
|
||||||
|
<dimen name="car_title2_size">32sp</dimen>
|
||||||
|
<dimen name="car_headline1_size">45sp</dimen>
|
||||||
|
<dimen name="car_headline2_size">32sp</dimen>
|
||||||
|
<dimen name="car_headline3_size">24sp</dimen>
|
||||||
|
<dimen name="car_headline4_size">20sp</dimen>
|
||||||
|
<dimen name="car_body1_size">32sp</dimen>
|
||||||
|
<dimen name="car_body2_size">28sp</dimen>
|
||||||
|
<dimen name="car_body3_size">26sp</dimen>
|
||||||
|
<dimen name="car_body4_size">24sp</dimen>
|
||||||
|
<!-- car_body5_size is deprecated -->
|
||||||
|
<dimen name="car_body5_size">18sp</dimen>
|
||||||
|
<dimen name="car_label1_size">26sp</dimen>
|
||||||
|
<dimen name="car_label2_size">64sp</dimen>
|
||||||
|
<dimen name="car_action1_size">26sp</dimen>
|
||||||
|
<dimen name="car_action2_size">26sp</dimen>
|
||||||
|
<!-- Paddings -->
|
||||||
|
<dimen name="car_padding_0">4dp</dimen>
|
||||||
|
<dimen name="car_padding_1">8dp</dimen>
|
||||||
|
<dimen name="car_padding_2">16dp</dimen>
|
||||||
|
<dimen name="car_padding_3">24dp</dimen>
|
||||||
|
<dimen name="car_padding_4">32dp</dimen>
|
||||||
|
<dimen name="car_padding_5">64dp</dimen>
|
||||||
|
<dimen name="car_padding_6">96dp</dimen>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Note: status bar height and navigation bar heights are defined
|
Note: status bar height and navigation bar heights are defined
|
||||||
in frameworks/base/core package and thus will have no effect if
|
in frameworks/base/core package and thus will have no effect if
|
||||||
@@ -156,4 +182,10 @@
|
|||||||
<dimen name="car_user_switcher_container_height">420dp</dimen>
|
<dimen name="car_user_switcher_container_height">420dp</dimen>
|
||||||
<!-- 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 car user switching dialog -->
|
||||||
|
<dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
|
||||||
|
<dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
|
||||||
|
<dimen name="car_user_switching_dialog_loading_text_margin_top">@*android:dimen/car_padding_4</dimen>
|
||||||
|
<dimen name="car_user_switching_dialog_loading_text_font_size">@*android:dimen/car_body1_size</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
<!-- String to represent lowest setting of an HVAC system [CHAR LIMIT=10]-->
|
<!-- String to represent lowest setting of an HVAC system [CHAR LIMIT=10]-->
|
||||||
<string name="hvac_min_text">Min</string>
|
<string name="hvac_min_text">Min</string>
|
||||||
<!-- String to represent largest setting of an HVAC system [CHAR LIMIT=10]-->
|
<!-- String to represent largest setting of an HVAC system [CHAR LIMIT=10]-->
|
||||||
@@ -34,4 +34,8 @@
|
|||||||
<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>
|
||||||
|
<!-- Message to inform user that the new user profile is loading. [CHAR LIMIT=20] -->
|
||||||
|
<string name="car_loading_profile">Loading</string>
|
||||||
|
<!-- Message to inform user that the new user profile is loading with additional information on the previous and the next user. [CHAR LIMIT=100] -->
|
||||||
|
<string name="car_loading_profile_developer_message">Loading user (from <xliff:g id="from_user" example="10">%1$d</xliff:g> to <xliff:g id="to_user" example="12">%2$d</xliff:g>)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -34,16 +34,19 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
|||||||
private final StatusBarStateController mStatusBarStateController;
|
private final StatusBarStateController mStatusBarStateController;
|
||||||
private final FullScreenUserSwitcherViewController mFullScreenUserSwitcherViewController;
|
private final FullScreenUserSwitcherViewController mFullScreenUserSwitcherViewController;
|
||||||
private final CarKeyguardViewController mCarKeyguardViewController;
|
private final CarKeyguardViewController mCarKeyguardViewController;
|
||||||
|
private final UserSwitchTransitionViewController mUserSwitchTransitionViewController;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FullscreenUserSwitcherViewMediator(
|
public FullscreenUserSwitcherViewMediator(
|
||||||
StatusBarStateController statusBarStateController,
|
StatusBarStateController statusBarStateController,
|
||||||
CarKeyguardViewController carKeyguardViewController,
|
CarKeyguardViewController carKeyguardViewController,
|
||||||
|
UserSwitchTransitionViewController userSwitchTransitionViewController,
|
||||||
FullScreenUserSwitcherViewController fullScreenUserSwitcherViewController) {
|
FullScreenUserSwitcherViewController fullScreenUserSwitcherViewController) {
|
||||||
|
|
||||||
mStatusBarStateController = statusBarStateController;
|
mStatusBarStateController = statusBarStateController;
|
||||||
mFullScreenUserSwitcherViewController = fullScreenUserSwitcherViewController;
|
|
||||||
mCarKeyguardViewController = carKeyguardViewController;
|
mCarKeyguardViewController = carKeyguardViewController;
|
||||||
|
mUserSwitchTransitionViewController = userSwitchTransitionViewController;
|
||||||
|
mFullScreenUserSwitcherViewController = fullScreenUserSwitcherViewController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -74,6 +77,11 @@ public class FullscreenUserSwitcherViewMediator implements OverlayViewMediator {
|
|||||||
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
|
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
|
||||||
if (record.mType != UserGridRecyclerView.UserRecord.FOREGROUND_USER) {
|
if (record.mType != UserGridRecyclerView.UserRecord.FOREGROUND_USER) {
|
||||||
mCarKeyguardViewController.hideKeyguardToPrepareBouncer();
|
mCarKeyguardViewController.hideKeyguardToPrepareBouncer();
|
||||||
|
// If guest user, we cannot use record.mInfo.id and should listen to the User lifecycle
|
||||||
|
// event instead.
|
||||||
|
if (record.mType != UserGridRecyclerView.UserRecord.START_GUEST) {
|
||||||
|
mUserSwitchTransitionViewController.handleShow(record.mInfo.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hide();
|
hide();
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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 static android.car.settings.CarSettings.Global.ENABLE_USER_SWITCH_DEVELOPER_MESSAGE;
|
||||||
|
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||||
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.car.window.OverlayViewController;
|
||||||
|
import com.android.systemui.car.window.OverlayViewGlobalStateController;
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles showing and hiding UserSwitchTransitionView that is mounted to SystemUiOverlayWindow.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class UserSwitchTransitionViewController extends OverlayViewController {
|
||||||
|
private static final String TAG = "UserSwitchTransitionViewController";
|
||||||
|
private static final String ENABLE_DEVELOPER_MESSAGE_TRUE = "true";
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final Handler mHandler;
|
||||||
|
private final Resources mResources;
|
||||||
|
private final UserManager mUserManager;
|
||||||
|
|
||||||
|
@GuardedBy("this")
|
||||||
|
private boolean mShowing;
|
||||||
|
private int mPreviousUserId = UserHandle.USER_NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public UserSwitchTransitionViewController(
|
||||||
|
Context context,
|
||||||
|
@Main Handler handler,
|
||||||
|
@Main Resources resources,
|
||||||
|
UserManager userManager,
|
||||||
|
OverlayViewGlobalStateController overlayViewGlobalStateController) {
|
||||||
|
|
||||||
|
super(R.id.user_switching_dialog_stub, overlayViewGlobalStateController);
|
||||||
|
|
||||||
|
mContext = context;
|
||||||
|
mHandler = handler;
|
||||||
|
mResources = resources;
|
||||||
|
mUserManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the user switch transition view appear and draws the content inside of it if a user
|
||||||
|
* that is different from the previous user is provided and if the dialog is not already
|
||||||
|
* showing.
|
||||||
|
*/
|
||||||
|
void handleShow(@UserIdInt int newUserId) {
|
||||||
|
if (mPreviousUserId == newUserId || mShowing) return;
|
||||||
|
mShowing = true;
|
||||||
|
mHandler.post(() -> {
|
||||||
|
start();
|
||||||
|
populateDialog(mPreviousUserId, newUserId);
|
||||||
|
// next time a new user is selected, this current new user will be the previous user.
|
||||||
|
mPreviousUserId = newUserId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleHide() {
|
||||||
|
if (!mShowing) return;
|
||||||
|
mShowing = false;
|
||||||
|
mHandler.post(this::stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateDialog(@UserIdInt int previousUserId, @UserIdInt int newUserId) {
|
||||||
|
drawUserIcon(newUserId);
|
||||||
|
populateLoadingText(previousUserId, newUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawUserIcon(int newUserId) {
|
||||||
|
Bitmap bitmap = mUserManager.getUserIcon(newUserId);
|
||||||
|
if (bitmap != null) {
|
||||||
|
CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(mContext, bitmap);
|
||||||
|
((ImageView) getLayout().findViewById(R.id.user_loading_avatar))
|
||||||
|
.setImageDrawable(drawable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateLoadingText(@UserIdInt int previousUserId, @UserIdInt int newUserId) {
|
||||||
|
TextView msgView = getLayout().findViewById(R.id.user_loading);
|
||||||
|
|
||||||
|
boolean showInfo = ENABLE_DEVELOPER_MESSAGE_TRUE.equals(
|
||||||
|
Settings.Global.getString(mContext.getContentResolver(),
|
||||||
|
ENABLE_USER_SWITCH_DEVELOPER_MESSAGE));
|
||||||
|
|
||||||
|
if (showInfo && mPreviousUserId != UserHandle.USER_NULL) {
|
||||||
|
msgView.setText(
|
||||||
|
mResources.getString(R.string.car_loading_profile_developer_message,
|
||||||
|
previousUserId, newUserId));
|
||||||
|
} else {
|
||||||
|
msgView.setText(mResources.getString(R.string.car_loading_profile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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.ActivityManager;
|
||||||
|
import android.car.Car;
|
||||||
|
import android.car.user.CarUserManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.systemui.car.CarServiceProvider;
|
||||||
|
import com.android.systemui.car.window.OverlayViewMediator;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers listeners that subscribe to events that show or hide CarUserSwitchingDialog that is
|
||||||
|
* mounted to SystemUiOverlayWindow.
|
||||||
|
*/
|
||||||
|
public class UserSwitchTransitionViewMediator implements OverlayViewMediator,
|
||||||
|
CarUserManager.UserSwitchUiCallback {
|
||||||
|
private static final String TAG = "UserSwitchTransitionViewMediator";
|
||||||
|
|
||||||
|
private final CarServiceProvider mCarServiceProvider;
|
||||||
|
private final UserSwitchTransitionViewController mUserSwitchTransitionViewController;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public UserSwitchTransitionViewMediator(
|
||||||
|
CarServiceProvider carServiceProvider,
|
||||||
|
UserSwitchTransitionViewController userSwitchTransitionViewController) {
|
||||||
|
mCarServiceProvider = carServiceProvider;
|
||||||
|
mUserSwitchTransitionViewController = userSwitchTransitionViewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerListeners() {
|
||||||
|
mCarServiceProvider.addListener(car -> {
|
||||||
|
CarUserManager carUserManager =
|
||||||
|
(CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE);
|
||||||
|
|
||||||
|
if (carUserManager != null) {
|
||||||
|
carUserManager.setUserSwitchUiCallback(this);
|
||||||
|
carUserManager.addListener(Runnable::run, this::handleUserLifecycleEvent);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "registerListeners: CarUserManager could not be obtained.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupOverlayContentViewControllers() {
|
||||||
|
// no-op.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showUserSwitchDialog(int userId) {
|
||||||
|
mUserSwitchTransitionViewController.handleShow(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void handleUserLifecycleEvent(CarUserManager.UserLifecycleEvent event) {
|
||||||
|
if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING
|
||||||
|
&& ActivityManager.getCurrentUser() == event.getUserId()) {
|
||||||
|
mUserSwitchTransitionViewController.handleShow(event.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
|
||||||
|
mUserSwitchTransitionViewController.handleHide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,9 @@ public interface OverlayViewMediator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Register listeners that could use ContentVisibilityAdjuster to show/hide content.
|
* Register listeners that could use ContentVisibilityAdjuster to show/hide content.
|
||||||
|
*
|
||||||
|
* Note that we do not unregister listeners because SystemUI components are expected to live
|
||||||
|
* for the lifecycle of the device.
|
||||||
*/
|
*/
|
||||||
void registerListeners();
|
void registerListeners();
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.android.systemui.car.notification.BottomNotificationPanelViewMediator
|
|||||||
import com.android.systemui.car.notification.NotificationPanelViewMediator;
|
import com.android.systemui.car.notification.NotificationPanelViewMediator;
|
||||||
import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
|
import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
|
||||||
import com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator;
|
import com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator;
|
||||||
|
import com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator;
|
||||||
|
|
||||||
import dagger.Binds;
|
import dagger.Binds;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
@@ -67,4 +68,11 @@ public abstract class OverlayWindowModule {
|
|||||||
@ClassKey(FullscreenUserSwitcherViewMediator.class)
|
@ClassKey(FullscreenUserSwitcherViewMediator.class)
|
||||||
public abstract OverlayViewMediator bindFullscreenUserSwitcherViewsMediator(
|
public abstract OverlayViewMediator bindFullscreenUserSwitcherViewsMediator(
|
||||||
FullscreenUserSwitcherViewMediator overlayViewsMediator);
|
FullscreenUserSwitcherViewMediator overlayViewsMediator);
|
||||||
|
|
||||||
|
/** Injects CarUserSwitchingDialogMediator. */
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ClassKey(UserSwitchTransitionViewMediator.class)
|
||||||
|
public abstract OverlayViewMediator bindUserSwitchTransitionViewMediator(
|
||||||
|
UserSwitchTransitionViewMediator userSwitchTransitionViewMediator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* 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 static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
import android.testing.TestableResources;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.car.window.OverlayViewGlobalStateController;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
@SmallTest
|
||||||
|
public class UserSwitchTransitionViewControllerTest extends SysuiTestCase {
|
||||||
|
private static final int TEST_USER_1 = 100;
|
||||||
|
private static final int TEST_USER_2 = 110;
|
||||||
|
|
||||||
|
private TestableUserSwitchTransitionViewController mCarUserSwitchingDialogController;
|
||||||
|
private TestableResources mTestableResources;
|
||||||
|
@Mock
|
||||||
|
private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mTestableResources = mContext.getOrCreateTestableResources();
|
||||||
|
mCarUserSwitchingDialogController = new TestableUserSwitchTransitionViewController(
|
||||||
|
mContext,
|
||||||
|
Handler.getMain(),
|
||||||
|
mTestableResources.getResources(),
|
||||||
|
(UserManager) mContext.getSystemService(Context.USER_SERVICE),
|
||||||
|
mOverlayViewGlobalStateController
|
||||||
|
);
|
||||||
|
|
||||||
|
mCarUserSwitchingDialogController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
|
||||||
|
R.layout.sysui_overlay_window, /* root= */ null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onHandleShow_newUserSelected_showsDialog() {
|
||||||
|
mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
|
||||||
|
|
||||||
|
verify(mOverlayViewGlobalStateController).showView(eq(mCarUserSwitchingDialogController),
|
||||||
|
any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onHandleShow_alreadyShowing_ignoresRequest() {
|
||||||
|
mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
|
||||||
|
mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_2);
|
||||||
|
|
||||||
|
// Verify that the request was processed only once.
|
||||||
|
verify(mOverlayViewGlobalStateController).showView(eq(mCarUserSwitchingDialogController),
|
||||||
|
any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onHandleShow_sameUserSelected_ignoresRequest() {
|
||||||
|
mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
|
||||||
|
mCarUserSwitchingDialogController.handleHide();
|
||||||
|
mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
|
||||||
|
|
||||||
|
// Verify that the request was processed only once.
|
||||||
|
verify(mOverlayViewGlobalStateController).showView(eq(mCarUserSwitchingDialogController),
|
||||||
|
any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onHide_currentlyShowing_hidesDialog() {
|
||||||
|
mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
|
||||||
|
mCarUserSwitchingDialogController.handleHide();
|
||||||
|
|
||||||
|
verify(mOverlayViewGlobalStateController).hideView(eq(mCarUserSwitchingDialogController),
|
||||||
|
any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onHide_notShowing_ignoresRequest() {
|
||||||
|
mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
|
||||||
|
mCarUserSwitchingDialogController.handleHide();
|
||||||
|
mCarUserSwitchingDialogController.handleHide();
|
||||||
|
|
||||||
|
// Verify that the request was processed only once.
|
||||||
|
verify(mOverlayViewGlobalStateController).hideView(eq(mCarUserSwitchingDialogController),
|
||||||
|
any());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class TestableUserSwitchTransitionViewController extends
|
||||||
|
UserSwitchTransitionViewController {
|
||||||
|
|
||||||
|
private final Handler mHandler;
|
||||||
|
|
||||||
|
TestableUserSwitchTransitionViewController(Context context, Handler handler,
|
||||||
|
Resources resources, UserManager userManager,
|
||||||
|
OverlayViewGlobalStateController overlayViewGlobalStateController) {
|
||||||
|
super(context, handler, resources, userManager, overlayViewGlobalStateController);
|
||||||
|
mHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleShow(int currentUserId) {
|
||||||
|
super.handleShow(currentUserId);
|
||||||
|
waitForIdleSync(mHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleHide() {
|
||||||
|
super.handleHide();
|
||||||
|
waitForIdleSync(mHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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 static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.car.user.CarUserManager;
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
|
||||||
|
import com.android.systemui.car.CarServiceProvider;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
@SmallTest
|
||||||
|
public class UserSwitchTransitionViewMediatorTest {
|
||||||
|
private static final int TEST_USER = 100;
|
||||||
|
|
||||||
|
private UserSwitchTransitionViewMediator mUserSwitchTransitionViewMediator;
|
||||||
|
@Mock
|
||||||
|
private CarServiceProvider mCarServiceProvider;
|
||||||
|
@Mock
|
||||||
|
private UserSwitchTransitionViewController mUserSwitchTransitionViewController;
|
||||||
|
@Mock
|
||||||
|
private CarUserManager.UserLifecycleEvent mUserLifecycleEvent;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
mUserSwitchTransitionViewMediator = new UserSwitchTransitionViewMediator(
|
||||||
|
mCarServiceProvider, mUserSwitchTransitionViewController);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onUserLifecycleEvent_userStarting_callsHandleShow() {
|
||||||
|
when(mUserLifecycleEvent.getEventType()).thenReturn(
|
||||||
|
CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING);
|
||||||
|
when(mUserLifecycleEvent.getUserId()).thenReturn(TEST_USER);
|
||||||
|
mUserSwitchTransitionViewMediator.handleUserLifecycleEvent(mUserLifecycleEvent);
|
||||||
|
|
||||||
|
verify(mUserSwitchTransitionViewController).handleShow(TEST_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onUserLifecycleEvent_userSwitching_callsHandleHide() {
|
||||||
|
when(mUserLifecycleEvent.getEventType()).thenReturn(
|
||||||
|
CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING);
|
||||||
|
mUserSwitchTransitionViewMediator.handleUserLifecycleEvent(mUserLifecycleEvent);
|
||||||
|
|
||||||
|
verify(mUserSwitchTransitionViewController).handleHide();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 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.server.am;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.UserInfo;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.ColorFilter;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Path;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.PorterDuffXfermode;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.os.UserManager;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowInsets;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.android.internal.R;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
|
|
||||||
* screen immediately after the dialog shows so that the user is informed that something is
|
|
||||||
* happening in the background rather than just freeze the screen and not know if the user-switch
|
|
||||||
* affordance was being handled.
|
|
||||||
*/
|
|
||||||
final class CarUserSwitchingDialog extends UserSwitchingDialog {
|
|
||||||
|
|
||||||
private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
|
|
||||||
private View mView;
|
|
||||||
|
|
||||||
public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
|
|
||||||
UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
|
|
||||||
String switchingToSystemUserMessage) {
|
|
||||||
super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
|
|
||||||
switchingToSystemUserMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void inflateContent() {
|
|
||||||
// Set up the dialog contents
|
|
||||||
setCancelable(false);
|
|
||||||
Resources res = getContext().getResources();
|
|
||||||
// Custom view due to alignment and font size requirements
|
|
||||||
getContext().setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
|
|
||||||
mView = LayoutInflater.from(getContext()).inflate(
|
|
||||||
R.layout.car_user_switching_dialog,
|
|
||||||
null);
|
|
||||||
|
|
||||||
UserManager userManager =
|
|
||||||
(UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
|
||||||
Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
|
|
||||||
if (bitmap != null) {
|
|
||||||
CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(bitmap,
|
|
||||||
res.getDimension(R.dimen.car_fullscreen_user_pod_image_avatar_height));
|
|
||||||
((ImageView) mView.findViewById(R.id.user_loading_avatar))
|
|
||||||
.setImageDrawable(drawable);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextView msgView = mView.findViewById(R.id.user_loading);
|
|
||||||
|
|
||||||
// TODO(b/145132885): use constant from CarSettings
|
|
||||||
boolean showInfo = "true".equals(Settings.Global.getString(
|
|
||||||
getContext().getContentResolver(),
|
|
||||||
"android.car.ENABLE_USER_SWITCH_DEVELOPER_MESSAGE"));
|
|
||||||
|
|
||||||
if (showInfo) {
|
|
||||||
msgView.setText(res.getString(R.string.car_loading_profile) + " user\n(from "
|
|
||||||
+ mOldUser.id + " to " + mNewUser.id + ")");
|
|
||||||
} else {
|
|
||||||
msgView.setText(res.getString(R.string.car_loading_profile));
|
|
||||||
}
|
|
||||||
setView(mView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void show() {
|
|
||||||
super.show();
|
|
||||||
hideNavigationBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hideNavigationBar() {
|
|
||||||
mView.getWindowInsetsController().hide(WindowInsets.Type.navigationBars());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the user icon to a circularly clipped one. This is used in the User Picker and
|
|
||||||
* Settings.
|
|
||||||
*/
|
|
||||||
static class CircleFramedDrawable extends Drawable {
|
|
||||||
|
|
||||||
private final Bitmap mBitmap;
|
|
||||||
private final int mSize;
|
|
||||||
private final Paint mPaint;
|
|
||||||
|
|
||||||
private float mScale;
|
|
||||||
private Rect mSrcRect;
|
|
||||||
private RectF mDstRect;
|
|
||||||
|
|
||||||
public static CircleFramedDrawable getInstance(Bitmap icon, float iconSize) {
|
|
||||||
CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CircleFramedDrawable(Bitmap icon, int size) {
|
|
||||||
super();
|
|
||||||
mSize = size;
|
|
||||||
|
|
||||||
mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
|
|
||||||
final Canvas canvas = new Canvas(mBitmap);
|
|
||||||
|
|
||||||
final int width = icon.getWidth();
|
|
||||||
final int height = icon.getHeight();
|
|
||||||
final int square = Math.min(width, height);
|
|
||||||
|
|
||||||
final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2,
|
|
||||||
square, square);
|
|
||||||
final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
|
|
||||||
|
|
||||||
final Path fillPath = new Path();
|
|
||||||
fillPath.addArc(circleRect, 0f, 360f);
|
|
||||||
|
|
||||||
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
|
||||||
|
|
||||||
// opaque circle
|
|
||||||
mPaint = new Paint();
|
|
||||||
mPaint.setAntiAlias(true);
|
|
||||||
mPaint.setColor(Color.BLACK);
|
|
||||||
mPaint.setStyle(Paint.Style.FILL);
|
|
||||||
canvas.drawPath(fillPath, mPaint);
|
|
||||||
|
|
||||||
// mask in the icon where the bitmap is opaque
|
|
||||||
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
|
||||||
canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
|
|
||||||
|
|
||||||
// prepare paint for frame drawing
|
|
||||||
mPaint.setXfermode(null);
|
|
||||||
|
|
||||||
mScale = 1f;
|
|
||||||
|
|
||||||
mSrcRect = new Rect(0, 0, mSize, mSize);
|
|
||||||
mDstRect = new RectF(0, 0, mSize, mSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(Canvas canvas) {
|
|
||||||
final float inside = mScale * mSize;
|
|
||||||
final float pad = (mSize - inside) / 2f;
|
|
||||||
|
|
||||||
mDstRect.set(pad, pad, mSize - pad, mSize - pad);
|
|
||||||
canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getOpacity() {
|
|
||||||
return PixelFormat.TRANSLUCENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAlpha(int alpha) {
|
|
||||||
// Needed to implement abstract method. Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setColorFilter(ColorFilter colorFilter) {
|
|
||||||
// Needed to implement abstract method. Do nothing.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2736,19 +2736,13 @@ class UserController implements Handler.Callback {
|
|||||||
|
|
||||||
void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
|
void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
|
||||||
String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
|
String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
|
||||||
Dialog d;
|
|
||||||
if (!mService.mContext.getPackageManager()
|
if (!mService.mContext.getPackageManager()
|
||||||
.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
|
.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
|
||||||
d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
|
final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser,
|
||||||
true /* above system */, switchingFromSystemUserMessage,
|
toUser, true /* above system */, switchingFromSystemUserMessage,
|
||||||
switchingToSystemUserMessage);
|
switchingToSystemUserMessage);
|
||||||
} else {
|
d.show();
|
||||||
d = new CarUserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
|
|
||||||
true /* above system */, switchingFromSystemUserMessage,
|
|
||||||
switchingToSystemUserMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reportGlobalUsageEventLocked(int event) {
|
void reportGlobalUsageEventLocked(int event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user