summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Julia Kawano <jkawano@google.com> 2020-08-17 23:24:16 +0000
committer Julia Kawano <juliakawano@google.com> 2020-08-27 22:59:41 +0000
commit224c81c6daa1f4fabebf42085b36bf8b83240034 (patch)
tree95e07228d573efb7fb34eca97010952ecc054712
parentcf259d52882cefd1b303cf5d4b6a0bcf88de1823 (diff)
Add username to status bar and update layout
Update the status bar with the new UX designs: - Remove driver and passenger HVAC views - Add driver icon (placeholder) and username aligned to start of bar - Move system icons aligned to end of bar (previously next to clock) - Add AM/PM to clock HVAC will be moved into the navigation bar in a separate change. Test: manual - change to guest, change username, change to long username (truncates before clock view) Test: atest :carsysui-presubmit Bug: 162598687 Change-Id: I5b9095adce7fee0970e8b15d307f01eb4adf2b40
-rw-r--r--packages/CarSystemUI/res/drawable/car_ic_user_icon.xml25
-rw-r--r--packages/CarSystemUI/res/layout/car_top_navigation_bar.xml100
-rw-r--r--packages/CarSystemUI/res/values/colors.xml2
-rw-r--r--packages/CarSystemUI/res/values/dimens.xml5
-rw-r--r--packages/CarSystemUI/res/values/styles.xml15
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java6
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java132
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java5
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java155
9 files changed, 371 insertions, 74 deletions
diff --git a/packages/CarSystemUI/res/drawable/car_ic_user_icon.xml b/packages/CarSystemUI/res/drawable/car_ic_user_icon.xml
new file mode 100644
index 000000000000..1195d05da228
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_user_icon.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/system_bar_icon_drawing_size"
+ android:height="@dimen/system_bar_icon_drawing_size"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"
+ android:fillColor="@color/system_bar_user_icon_color"/>
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
index cdc29eec21cd..af8482a8c6a5 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -31,39 +31,44 @@
android:layoutDirection="ltr">
<FrameLayout
- android:id="@+id/left_hvac_container"
+ android:id="@+id/user_name_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
+ android:layout_toStartOf="@+id/clock_container"
>
<com.android.systemui.car.navigationbar.CarNavigationButton
- android:id="@+id/hvacleft"
+ android:id="@+id/user_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@null"
- systemui:broadcast="true"
- systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
- />
-
- <com.android.systemui.car.hvac.AnimatedTemperatureView
- android:id="@+id/lefttext"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingStart="@*android:dimen/car_padding_4"
- android:paddingEnd="16dp"
- android:gravity="center_vertical|start"
- android:minEms="4"
- android:textAppearance="@style/TextAppearance.CarStatus"
- systemui:hvacAreaId="49"
- systemui:hvacMaxText="@string/hvac_max_text"
- systemui:hvacMaxValue="@dimen/hvac_max_value"
- systemui:hvacMinText="@string/hvac_min_text"
- systemui:hvacMinValue="@dimen/hvac_min_value"
- systemui:hvacPivotOffset="60dp"
- systemui:hvacPropertyId="358614275"
- systemui:hvacTempFormat="%.0f\u00B0"
- />
+ systemui:icon="@null"
+ systemui:intent="intent:#Intent;component=com.android.car.settings/.users.UserSwitcherActivity;launchFlags=0x24000000;end"
+ >
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ >
+ <ImageView
+ android:id="@+id/user_avatar"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:src="@drawable/car_ic_user_icon"
+ android:paddingLeft="@dimen/system_bar_user_icon_padding"
+ android:paddingRight="@dimen/system_bar_user_icon_padding"
+ />
+ <TextView
+ android:id="@+id/user_name_text"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:textAppearance="@style/TextAppearance.SystemBar.Username"
+ android:maxLines="1"
+ />
+ </LinearLayout>
+ </com.android.systemui.car.navigationbar.CarNavigationButton>
</FrameLayout>
<FrameLayout
@@ -86,7 +91,8 @@
android:layout_gravity="center"
android:elevation="5dp"
android:singleLine="true"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:textAppearance="@style/TextAppearance.SystemBar.Clock"
+ systemui:amPmStyle="normal"
/>
</FrameLayout>
@@ -94,10 +100,9 @@
android:id="@+id/system_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_centerHorizontal="true"
+ android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
- android:layout_toEndOf="@+id/clock_container"
- android:paddingStart="@*android:dimen/car_padding_1"
+ android:paddingEnd="@*android:dimen/car_padding_1"
android:gravity="center_vertical"
android:orientation="horizontal"
>
@@ -107,46 +112,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:paddingStart="4dp"
android:gravity="center_vertical"
/>
</LinearLayout>
-
- <FrameLayout
- android:id="@+id/right_hvac_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignParentEnd="true"
- >
-
- <com.android.systemui.car.navigationbar.CarNavigationButton
- android:id="@+id/hvacright"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@null"
- systemui:broadcast="true"
- systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
- />
-
- <com.android.systemui.car.hvac.AnimatedTemperatureView
- android:id="@+id/righttext"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingStart="16dp"
- android:paddingEnd="@*android:dimen/car_padding_4"
- android:gravity="center_vertical|end"
- android:minEms="4"
- android:textAppearance="@style/TextAppearance.CarStatus"
- systemui:hvacAreaId="68"
- systemui:hvacMaxText="@string/hvac_max_text"
- systemui:hvacMaxValue="@dimen/hvac_max_value"
- systemui:hvacMinText="@string/hvac_min_text"
- systemui:hvacMinValue="@dimen/hvac_min_value"
- systemui:hvacPivotOffset="60dp"
- systemui:hvacPropertyId="358614275"
- systemui:hvacTempFormat="%.0f\u00B0"
- />
- </FrameLayout>
</RelativeLayout>
</com.android.systemui.car.navigationbar.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
index ab9426593535..98e31b31551e 100644
--- a/packages/CarSystemUI/res/values/colors.xml
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -31,6 +31,8 @@
<color name="docked_divider_background">@*android:color/car_grey_50</color>
<color name="system_bar_background_opaque">#ff172026</color>
+ <!-- colors for status bar -->
+ <color name="system_bar_user_icon_color">#ffffff</color>
<color name="status_bar_background_color">#33000000</color>
<drawable name="system_bar_background">@color/status_bar_background_color</drawable>
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index 8359dac6a30f..5fb32aff27e8 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -46,8 +46,9 @@
in frameworks/base/core package and thus will have no effect if
set here. See car_product overlay for car specific defaults-->
- <dimen name="status_bar_icon_drawing_size_dark">36dp</dimen>
- <dimen name="status_bar_icon_drawing_size">36dp</dimen>
+ <dimen name="system_bar_user_icon_padding">16dp</dimen>
+ <dimen name="system_bar_icon_drawing_size_dark">36dp</dimen>
+ <dimen name="system_bar_icon_drawing_size">36dp</dimen>
<!-- The amount by which to scale up the status bar icons. -->
<item name="status_bar_icon_scale_factor" format="float" type="dimen">1.75</item>
diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml
index e76373d4a4f7..5b042a4b83ec 100644
--- a/packages/CarSystemUI/res/values/styles.xml
+++ b/packages/CarSystemUI/res/values/styles.xml
@@ -25,11 +25,16 @@
<item name="android:padding">22dp</item>
</style>
- <style name="TextAppearance.StatusBar.Clock"
- parent="@*android:style/TextAppearance.StatusBar.Icon">
- <item name="android:textSize">42sp</item>
- <item name="android:fontFamily">sans-serif-regular</item>
- <item name="android:textColor">@*android:color/car_grey_50</item>
+ <style name="TextAppearance.SystemBar.Clock"
+ parent="@*android:style/TextAppearance.StatusBar.Icon">
+ <item name="android:textSize">@dimen/car_body1_size</item>
+ <item name="android:textColor">@*android:color/car_headline3</item>
+ </style>
+
+ <style name="TextAppearance.SystemBar.Username"
+ parent="@android:style/TextAppearance.DeviceDefault">
+ <item name="android:textSize">@dimen/car_body3_size</item>
+ <item name="android:textColor">@*android:color/car_headline3</item>
</style>
<style name="TextAppearance.CarStatus" parent="@android:style/TextAppearance.DeviceDefault">
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
index 51a883809aab..529083f4bab6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
@@ -23,6 +23,7 @@ import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.android.systemui.car.hvac.HvacController;
+import com.android.systemui.car.statusbar.UserNameViewController;
import com.android.systemui.dagger.SysUISingleton;
import javax.inject.Inject;
@@ -38,6 +39,7 @@ public class CarNavigationBarController {
private final ButtonSelectionStateController mButtonSelectionStateController;
private final ButtonRoleHolderController mButtonRoleHolderController;
private final Lazy<HvacController> mHvacControllerLazy;
+ private final Lazy<UserNameViewController> mUserNameViewControllerLazy;
private boolean mShowTop;
private boolean mShowBottom;
@@ -60,12 +62,14 @@ public class CarNavigationBarController {
NavigationBarViewFactory navigationBarViewFactory,
ButtonSelectionStateController buttonSelectionStateController,
Lazy<HvacController> hvacControllerLazy,
+ Lazy<UserNameViewController> userNameViewControllerLazy,
ButtonRoleHolderController buttonRoleHolderController,
SystemBarConfigs systemBarConfigs) {
mContext = context;
mNavigationBarViewFactory = navigationBarViewFactory;
mButtonSelectionStateController = buttonSelectionStateController;
mHvacControllerLazy = hvacControllerLazy;
+ mUserNameViewControllerLazy = userNameViewControllerLazy;
mButtonRoleHolderController = buttonRoleHolderController;
// Read configuration.
@@ -109,6 +113,7 @@ public class CarNavigationBarController {
mHvacControllerLazy.get().removeAllComponents();
mButtonSelectionStateController.removeAll();
mButtonRoleHolderController.removeAll();
+ mUserNameViewControllerLazy.get().removeAll();
}
/** Gets the top window if configured to do so. */
@@ -218,6 +223,7 @@ public class CarNavigationBarController {
mButtonSelectionStateController.addAllButtonsWithSelectionState(view);
mButtonRoleHolderController.addAllButtonsWithRoleName(view);
mHvacControllerLazy.get().addTemperatureViewToController(view);
+ mUserNameViewControllerLazy.get().addUserNameView(view);
}
/** Sets a touch listener for the top navigation bar. */
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java
new file mode 100644
index 000000000000..5ef8aa19b182
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UserNameViewController.java
@@ -0,0 +1,132 @@
+/*
+ * 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.statusbar;
+
+import android.car.Car;
+import android.car.user.CarUserManager;
+import android.content.BroadcastReceiver;
+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.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.car.CarDeviceProvisionedController;
+import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.dagger.SysUISingleton;
+
+import javax.inject.Inject;
+
+/**
+ * Controls a TextView with the current driver's username
+ */
+@SysUISingleton
+public class UserNameViewController {
+ private static final String TAG = "UserNameViewController";
+
+ private Context mContext;
+ private UserManager mUserManager;
+ private CarUserManager mCarUserManager;
+ private CarServiceProvider mCarServiceProvider;
+ private CarDeviceProvisionedController mCarDeviceProvisionedController;
+ private BroadcastDispatcher mBroadcastDispatcher;
+ private TextView mUserNameView;
+
+ private final BroadcastReceiver mUserUpdateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateUser(mCarDeviceProvisionedController.getCurrentUser());
+ }
+ };
+
+ private final CarUserManager.UserLifecycleListener mUserLifecycleListener =
+ new CarUserManager.UserLifecycleListener() {
+ @Override
+ public void onEvent(CarUserManager.UserLifecycleEvent event) {
+ if (event.getEventType()
+ == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
+ updateUser(event.getUserId());
+ }
+ }
+ };
+
+ @Inject
+ public UserNameViewController(Context context, CarServiceProvider carServiceProvider,
+ UserManager userManager, BroadcastDispatcher broadcastDispatcher,
+ CarDeviceProvisionedController carDeviceProvisionedController) {
+ mContext = context;
+ mCarServiceProvider = carServiceProvider;
+ mUserManager = userManager;
+ mBroadcastDispatcher = broadcastDispatcher;
+ mCarDeviceProvisionedController = carDeviceProvisionedController;
+ }
+
+ /**
+ * Find the {@link TextView} for the driver's user name from a view and if found set it with the
+ * current driver's user name.
+ */
+ public void addUserNameView(View v) {
+ TextView userNameView = v.findViewById(R.id.user_name_text);
+ if (userNameView != null) {
+ if (mUserNameView == null) {
+ registerForUserChangeEvents();
+ }
+ mUserNameView = userNameView;
+ updateUser(mCarDeviceProvisionedController.getCurrentUser());
+ }
+ }
+
+ /**
+ * Clean up the controller and unregister receiver.
+ */
+ public void removeAll() {
+ mBroadcastDispatcher.unregisterReceiver(mUserUpdateReceiver);
+ if (mCarUserManager != null) {
+ mCarUserManager.removeListener(mUserLifecycleListener);
+ }
+ }
+
+ private void registerForUserChangeEvents() {
+ // Register for user switching
+ mCarServiceProvider.addListener(car -> {
+ mCarUserManager = (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE);
+ if (mCarUserManager != null) {
+ mCarUserManager.addListener(Runnable::run, mUserLifecycleListener);
+ } else {
+ Log.e(TAG, "CarUserManager could not be obtained.");
+ }
+ });
+ // Also register for user info changing
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+ mBroadcastDispatcher.registerReceiver(mUserUpdateReceiver, filter, /* executor= */ null,
+ UserHandle.ALL);
+ }
+
+ private void updateUser(int userId) {
+ if (mUserNameView != null) {
+ UserInfo currentUserInfo = mUserManager.getUserInfo(userId);
+ mUserNameView.setText(currentUserInfo.name);
+ }
+ }
+}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
index 0b164a2e1a51..5ca6b9bba2e4 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
@@ -33,6 +33,7 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarSystemUiTest;
import com.android.systemui.car.hvac.HvacController;
+import com.android.systemui.car.statusbar.UserNameViewController;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -58,6 +59,8 @@ public class CarNavigationBarControllerTest extends SysuiTestCase {
private ButtonRoleHolderController mButtonRoleHolderController;
@Mock
private HvacController mHvacController;
+ @Mock
+ private UserNameViewController mUserNameViewController;
@Before
public void setUp() throws Exception {
@@ -73,7 +76,7 @@ public class CarNavigationBarControllerTest extends SysuiTestCase {
private CarNavigationBarController createNavigationBarController() {
return new CarNavigationBarController(mContext, mNavigationBarViewFactory,
mButtonSelectionStateController, () -> mHvacController,
- mButtonRoleHolderController,
+ () -> mUserNameViewController, mButtonRoleHolderController,
new SystemBarConfigs(mTestableResources.getResources()));
}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java
new file mode 100644
index 000000000000..8f9e56edf419
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/statusbar/UserNameViewControllerTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.statusbar;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.car.Car;
+import android.car.user.CarUserManager;
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.car.CarDeviceProvisionedController;
+import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.CarSystemUiTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@CarSystemUiTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class UserNameViewControllerTest extends SysuiTestCase {
+
+ private final UserInfo mUserInfo1 = new UserInfo(/* id= */ 0, "Test User Name", /* flags= */ 0);
+ private final UserInfo mUserInfo2 = new UserInfo(/* id= */ 1, "Another User", /* flags= */ 0);
+ private TextView mTextView;
+ private UserNameViewController mUserNameViewController;
+
+ @Mock
+ private Car mCar;
+ @Mock
+ private CarUserManager mCarUserManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private CarDeviceProvisionedController mCarDeviceProvisionedController;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mUserManager.getUserInfo(mUserInfo1.id)).thenReturn(mUserInfo1);
+ when(mUserManager.getUserInfo(mUserInfo2.id)).thenReturn(mUserInfo2);
+ when(mCar.isConnected()).thenReturn(true);
+ when(mCar.getCarManager(Car.CAR_USER_SERVICE)).thenReturn(mCarUserManager);
+
+ CarServiceProvider carServiceProvider = new CarServiceProvider(mContext, mCar);
+ mUserNameViewController = new UserNameViewController(getContext(), carServiceProvider,
+ mUserManager, mBroadcastDispatcher, mCarDeviceProvisionedController);
+
+ mTextView = new TextView(getContext());
+ mTextView.setId(R.id.user_name_text);
+ }
+
+ @Test
+ public void addUserNameViewToController_updatesUserNameView() {
+ when(mCarDeviceProvisionedController.getCurrentUser()).thenReturn(mUserInfo1.id);
+
+ mUserNameViewController.addUserNameView(mTextView);
+
+ assertEquals(mTextView.getText(), mUserInfo1.name);
+ }
+
+ @Test
+ public void addUserNameViewToController_withNoTextView_doesNotUpdate() {
+ View nullView = new View(getContext());
+ mUserNameViewController.addUserNameView(nullView);
+
+ assertEquals(mTextView.getText(), "");
+ verifyZeroInteractions(mCarDeviceProvisionedController);
+ verifyZeroInteractions(mCarUserManager);
+ verifyZeroInteractions(mUserManager);
+ }
+
+ @Test
+ public void userLifecycleListener_onUserSwitchLifecycleEvent_updatesUserNameView() {
+ ArgumentCaptor<CarUserManager.UserLifecycleListener> userLifecycleListenerArgumentCaptor =
+ ArgumentCaptor.forClass(CarUserManager.UserLifecycleListener.class);
+ when(mCarDeviceProvisionedController.getCurrentUser()).thenReturn(mUserInfo1.id);
+ // Add the initial TextView, which registers the UserLifecycleListener
+ mUserNameViewController.addUserNameView(mTextView);
+ assertEquals(mTextView.getText(), mUserInfo1.name);
+ verify(mCarUserManager).addListener(any(), userLifecycleListenerArgumentCaptor.capture());
+
+ CarUserManager.UserLifecycleEvent event = new CarUserManager.UserLifecycleEvent(
+ CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, /* from= */ mUserInfo1.id,
+ /* to= */ mUserInfo2.id);
+ userLifecycleListenerArgumentCaptor.getValue().onEvent(event);
+
+ assertEquals(mTextView.getText(), mUserInfo2.name);
+ }
+
+ @Test
+ public void userInfoChangedBroadcast_withoutInitializingUserNameView_doesNothing() {
+ getContext().sendBroadcast(new Intent(Intent.ACTION_USER_INFO_CHANGED));
+
+ assertEquals(mTextView.getText(), "");
+ verifyZeroInteractions(mCarDeviceProvisionedController);
+ }
+
+ @Test
+ public void userInfoChangedBroadcast_withUserNameViewInitialized_updatesUserNameView() {
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverArgumentCaptor = ArgumentCaptor.forClass(
+ BroadcastReceiver.class);
+ when(mCarDeviceProvisionedController.getCurrentUser()).thenReturn(mUserInfo1.id);
+ mUserNameViewController.addUserNameView(mTextView);
+ assertEquals(mTextView.getText(), mUserInfo1.name);
+ verify(mBroadcastDispatcher).registerReceiver(broadcastReceiverArgumentCaptor.capture(),
+ any(), any(), any());
+
+ reset(mCarDeviceProvisionedController);
+ when(mCarDeviceProvisionedController.getCurrentUser()).thenReturn(mUserInfo2.id);
+ broadcastReceiverArgumentCaptor.getValue().onReceive(getContext(),
+ new Intent(Intent.ACTION_USER_INFO_CHANGED));
+
+ assertEquals(mTextView.getText(), mUserInfo2.name);
+ verify(mCarDeviceProvisionedController).getCurrentUser();
+ }
+}