Fix asynchronous problems in Trusted Device in CarSettings
This change will fix:
(1) Settings will be closed if we call goBack in ActivityResultCallBack.
(2) Settings crash when call goBack when the fragment is starting, add postOnMainThread control will solve the concurrency issue.
Bug: 128913807
Test: Build and flash, Robolectric test
Change-Id: Ic40cb8563fefc0181181edb8bae1d4955ebda831
(cherry picked from commit 76dd680cf6ed0811f37e61622c81866a0dc36031)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a4fed8d..60f23d2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,11 +17,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.car.settings"
- coreApp="true"
- android:sharedUserId="android.uid.system"
- android:versionCode="1"
- android:versionName="1.0">
+ package="com.android.car.settings"
+ coreApp="true"
+ android:sharedUserId="android.uid.system"
+ android:versionCode="1"
+ android:versionName="1.0">
<uses-sdk
android:minSdkVersion="24"
@@ -258,6 +258,11 @@
android:windowSoftInputMode="adjustResize">
</activity>
+ <activity android:name=".security.AddTrustedDeviceActivity"
+ android:configChanges="orientation|keyboardHidden|screenSize"
+ android:windowSoftInputMode="adjustResize">
+ </activity>
+
<activity android:name=".system.ThirdPartyLicensesActivity"
android:label="@string/settings_license_activity_title"
android:configChanges="orientation|keyboardHidden|screenSize"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d88932d..1b7092f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1034,6 +1034,8 @@
<string name="trusted_device_fail_enrollment_toast"><xliff:g id="device_name" example="Pixel2">%1$s</xliff:g> enrollment failed</string>
<!-- Message shown when user have not set authentication [CHAR LIMIT=NONE]-->
<string name="trusted_device_set_authentication_reminder">Adding a trusted device requires you to set an authentication method next. If you do not have your trusted device with you, authentication will be required to access your profile.</string>
+ <!-- Toast shown when phone is disconnected [CHAR LIMIT=50]-->
+ <string name="trusted_device_disconnected_toast">Device disconnected.</string>
<!-- generic --><skip/>
<!-- Button label for generic forget action [CHAR LIMIT=20] -->
diff --git a/res/xml/choose_trusted_device_fragment.xml b/res/xml/choose_trusted_device_fragment.xml
index a8bbd4f..261b9b9 100644
--- a/res/xml/choose_trusted_device_fragment.xml
+++ b/res/xml/choose_trusted_device_fragment.xml
@@ -21,9 +21,12 @@
android:key="@string/pk_trusted_device_list"
settings:controller="com.android.car.settings.security.TrustedDeviceListPreferenceController"/>
<Preference
- android:fragment="com.android.car.settings.security.AddTrustedDeviceProgressFragment"
android:icon="@drawable/ic_add"
android:key="@string/pk_add_trusted_device"
android:title="@string/add_device_title"
- settings:controller="com.android.car.settings.security.AddTrustedDevicePreferenceController"/>
-</PreferenceScreen>
\ No newline at end of file
+ settings:controller="com.android.car.settings.security.AddTrustedDevicePreferenceController">
+ <intent
+ android:targetClass="com.android.car.settings.security.AddTrustedDeviceActivity"
+ android:targetPackage="com.android.car.settings"/>
+ </Preference>
+</PreferenceScreen>
diff --git a/src/com/android/car/settings/security/AddTrustedDeviceActivity.java b/src/com/android/car/settings/security/AddTrustedDeviceActivity.java
new file mode 100644
index 0000000..3cce575
--- /dev/null
+++ b/src/com/android/car/settings/security/AddTrustedDeviceActivity.java
@@ -0,0 +1,239 @@
+/*
+ * 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.car.settings.security;
+
+import android.bluetooth.BluetoothDevice;
+import android.car.Car;
+import android.car.trust.CarTrustAgentEnrollmentManager;
+import android.car.userlib.CarUserManagerHelper;
+import android.os.Bundle;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.CarSettingActivity;
+import com.android.car.settings.common.Logger;
+
+/**
+ * Activity which manages the enrollment process and communicates between
+ * CarTrustAgentEnrollmentService and fragments.
+ *
+ * <p>The flow when user want to enroll a trusted device should be as follows:
+ * <ol>
+ * <li> {@link CarTrustAgentEnrollmentManager#setEnrollmentCallback(
+ *CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback)}
+ * <li> {@link CarTrustAgentEnrollmentManager#setBleCallback(
+ *CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback)}
+ * <li> {@link CarTrustAgentEnrollmentManager#startEnrollmentAdvertising()}
+ * <li> wait for {@link CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback#
+ * onBleEnrollmentDeviceDisconnected(BluetoothDevice)}
+ * <li> if connected, call {@link CarTrustAgentEnrollmentManager#initiateEnrollmentHandshake(
+ *BluetoothDevice)}
+ * <li> {@link CarTrustAgentEnrollmentManager#stopEnrollmentAdvertising()}
+ * <li> wait for
+ * {@link CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback#onAuthStringAvailable(
+ *BluetoothDevice, String)} to show the pairing code dialog to user
+ * <li> {@link CarTrustAgentEnrollmentManager#enrollmentHandshakeAccepted(BluetoothDevice)} after
+ * user confirms the pairing code
+ * <li> wait for
+ * {@link CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback#onEscrowTokenAdded(long)}
+ * <li> {@link #getCheckLockFragment()}, wait user to input the password
+ * <li> After user enter the correct password, wait for
+ * {@link CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback#
+ * onEscrowTokenActiveStateChanged(long, boolean)}
+ * <li> After get the results, finish the activity
+ * </ol>
+ */
+public class AddTrustedDeviceActivity extends CarSettingActivity implements CheckLockListener {
+ private static final Logger LOG = new Logger(AddTrustedDeviceActivity.class);
+ private static final String BLUETOOTH_DEVICE_KEY = "bluetoothDevice";
+ private static final String CURRENT_HANDLE_KEY = "currentHandle";
+ private Car mCar;
+ private BluetoothDevice mBluetoothDevice;
+ private long mHandle;
+ private CarUserManagerHelper mCarUserManagerHelper;
+ @Nullable
+ private CarTrustAgentEnrollmentManager mCarTrustAgentEnrollmentManager;
+
+ private final CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback
+ mCarTrustAgentEnrollmentCallback =
+ new CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback() {
+
+ @Override
+ public void onEnrollmentHandshakeFailure(BluetoothDevice device, int errorCode) {
+ LOG.e("Trust agent service time out");
+ }
+
+ @Override
+ public void onAuthStringAvailable(BluetoothDevice device, String authString) {
+ ConfirmPairingCodeDialog dialog = ConfirmPairingCodeDialog.newInstance(
+ device.getAddress(), authString);
+ dialog.setConfirmPairingCodeListener(mConfirmParingCodeListener);
+ showDialog(dialog, ConfirmPairingCodeDialog.TAG);
+ }
+
+ @Override
+ public void onEscrowTokenAdded(long handle) {
+ // User need to enter the correct authentication of the car to activate the
+ // added token.
+ mHandle = handle;
+ launchFragment(getCheckLockFragment());
+ }
+
+ @Override
+ public void onEscrowTokenRemoved(long handle) {
+ }
+
+ @Override
+ public void onEscrowTokenActiveStateChanged(long handle, boolean active) {
+ if (active) {
+ onDeviceAddedSuccessfully(handle);
+ } else {
+ LOG.d(handle + " has not been activated");
+ }
+ finish();
+ }
+ };
+
+ private final CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback
+ mCarTrustAgentBleCallback =
+ new CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback() {
+ @Override
+ public void onBleEnrollmentDeviceConnected(BluetoothDevice device) {
+ mBluetoothDevice = device;
+ mCarTrustAgentEnrollmentManager.stopEnrollmentAdvertising();
+ }
+
+ @Override
+ public void onBleEnrollmentDeviceDisconnected(BluetoothDevice device) {
+ Toast.makeText(AddTrustedDeviceActivity.this, getResources().getString(
+ R.string.trusted_device_disconnected_toast),
+ Toast.LENGTH_SHORT).show();
+ mBluetoothDevice = null;
+ finish();
+ }
+
+ @Override
+ public void onEnrollmentAdvertisingStarted() {
+ }
+
+ @Override
+ public void onEnrollmentAdvertisingFailed() {
+ finish();
+ }
+ };
+
+ @VisibleForTesting
+ final ConfirmPairingCodeDialog.ConfirmPairingCodeListener mConfirmParingCodeListener =
+ new ConfirmPairingCodeDialog.ConfirmPairingCodeListener() {
+ public void onConfirmPairingCode() {
+ mCarTrustAgentEnrollmentManager.enrollmentHandshakeAccepted(mBluetoothDevice);
+ }
+
+ public void onDialogCancelled() {
+ finish();
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mCar = Car.createCar(this);
+ mCarTrustAgentEnrollmentManager = (CarTrustAgentEnrollmentManager) mCar.getCarManager(
+ Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE);
+ if (mCarTrustAgentEnrollmentManager == null) {
+ LOG.e("CarTrustAgentEnrollmentManager is null");
+ finish();
+ }
+ mCarUserManagerHelper = new CarUserManagerHelper(this);
+ if (savedInstanceState != null) {
+ mBluetoothDevice = savedInstanceState.getParcelable(BLUETOOTH_DEVICE_KEY);
+ mHandle = savedInstanceState.getLong(CURRENT_HANDLE_KEY);
+ }
+ ConfirmPairingCodeDialog dialog =
+ (ConfirmPairingCodeDialog) findDialogByTag(ConfirmPairingCodeDialog.TAG);
+ if (dialog != null) {
+ dialog.setConfirmPairingCodeListener(mConfirmParingCodeListener);
+ }
+ }
+
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (mHandle != 0) {
+ if (mCarTrustAgentEnrollmentManager.isEscrowTokenActive(mHandle,
+ mCarUserManagerHelper.getCurrentProcessUserId())) {
+ onDeviceAddedSuccessfully(mHandle);
+ finish();
+ }
+ }
+ if (mBluetoothDevice == null) {
+ mCarTrustAgentEnrollmentManager.startEnrollmentAdvertising();
+ }
+ mCarTrustAgentEnrollmentManager.setEnrollmentCallback(mCarTrustAgentEnrollmentCallback);
+ mCarTrustAgentEnrollmentManager.setBleCallback(mCarTrustAgentBleCallback);
+
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mCarTrustAgentEnrollmentManager.setBleCallback(null);
+ mCarTrustAgentEnrollmentManager.setEnrollmentCallback(null);
+ mCarTrustAgentEnrollmentManager.stopEnrollmentAdvertising();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ savedInstanceState.putParcelable(BLUETOOTH_DEVICE_KEY, mBluetoothDevice);
+ savedInstanceState.putLong(CURRENT_HANDLE_KEY, mHandle);
+ super.onSaveInstanceState(savedInstanceState);
+ }
+
+
+ @Override
+ @Nullable
+ protected Fragment getFragment() {
+ Fragment currentFragment = getSupportFragmentManager().findFragmentById(
+ R.id.fragment_container);
+ return currentFragment == null ? new AddTrustedDeviceProgressFragment() : currentFragment;
+ }
+
+ private Fragment getCheckLockFragment() {
+ return ConfirmPasswordFragmentFactory.getFragment(/* context= */ this);
+ }
+
+ @Override
+ public void onLockVerified(byte[] lock) {
+ getSupportFragmentManager().popBackStack();
+ }
+
+ @Override
+ public void onBackPressed() {
+ finish();
+ }
+
+ private void onDeviceAddedSuccessfully(long handle) {
+ Toast.makeText(this,
+ getResources().getString(R.string.trusted_device_success_enrollment_toast),
+ Toast.LENGTH_LONG).show();
+ }
+}
diff --git a/src/com/android/car/settings/security/AddTrustedDevicePreferenceController.java b/src/com/android/car/settings/security/AddTrustedDevicePreferenceController.java
index f48a54d..7dc6428 100644
--- a/src/com/android/car/settings/security/AddTrustedDevicePreferenceController.java
+++ b/src/com/android/car/settings/security/AddTrustedDevicePreferenceController.java
@@ -16,151 +16,29 @@
package com.android.car.settings.security;
-import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
-import android.bluetooth.BluetoothDevice;
-import android.car.Car;
-import android.car.CarNotConnectedException;
import android.car.drivingstate.CarUxRestrictions;
-import android.car.trust.CarTrustAgentEnrollmentManager;
import android.car.userlib.CarUserManagerHelper;
import android.content.Context;
-import android.content.Intent;
-import android.widget.Toast;
-import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
-import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
-import com.android.car.settings.common.Logger;
import com.android.car.settings.common.PreferenceController;
import com.android.internal.widget.LockPatternUtils;
/**
- * Business logic when user click on add trusted device, a new screen will be shown and user can add
- * a trusted device using CarTrustAgentEnrollmentManager, confirm pairing code dialog base on that.
- * TODO(wentingzhai): test the enrollment process when CarTrustAgentEnrollment Service is done.
+ * Business logic if the preference is clickable according to the password quality of current user.
*/
public class AddTrustedDevicePreferenceController extends PreferenceController<Preference> {
-
- private static final Logger LOG = new Logger(AddTrustedDevicePreferenceController.class);
- private final Car mCar;
- private final CarUserManagerHelper mCarUserManagerHelper;
- private final LockPatternUtils mLockPatternUtils;
- private BluetoothDevice mBluetoothDevice;
- @Nullable
- private CarTrustAgentEnrollmentManager mCarTrustAgentEnrollmentManager;
-
- private final CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback
- mCarTrustAgentEnrollmentCallback =
- new CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback() {
-
- @Override
- public void onEnrollmentHandshakeFailure(BluetoothDevice device, int errorCode) {
- LOG.e("Trust agent service time out");
- }
-
- @Override
- public void onAuthStringAvailable(BluetoothDevice device, String authString) {
- ConfirmPairingCodeDialog dialog = ConfirmPairingCodeDialog.newInstance(
- device.getName(), authString);
- dialog.setConfirmPairingCodeListener(mConfirmParingCodeListener);
- getFragmentController().showDialog(dialog, ConfirmPairingCodeDialog.TAG);
- }
-
- @Override
- public void onEscrowTokenAdded(long handle) {
- // User need to enter the correct authentication of the car to activate the
- // added token.
- getContext().startActivity(new Intent(getContext(), CheckLockActivity.class));
- }
-
- @Override
- public void onEscrowTokenRemoved(long handle) {
- }
-
- @Override
- public void onEscrowTokenActiveStateChanged(long handle, boolean active) {
- if (active) {
- Toast.makeText(getContext(), getContext().getString(
- R.string.trusted_device_success_enrollment_toast),
- Toast.LENGTH_LONG).show();
- } else {
- LOG.d(handle + " has been deactivated");
- }
- try {
- mCarTrustAgentEnrollmentManager.stopEnrollmentAdvertising();
- mCarTrustAgentEnrollmentManager.setBleCallback(null);
- mCarTrustAgentEnrollmentManager.setEnrollmentCallback(null);
- } catch (CarNotConnectedException e) {
- LOG.e(e.getMessage(), e);
- }
- getFragmentController().goBack();
- }
- };
-
- private final CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback
- mCarTrustAgentBleCallback =
- new CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback() {
- @Override
- public void onBleEnrollmentDeviceConnected(BluetoothDevice device) {
- mBluetoothDevice = device;
- }
-
- @Override
- public void onBleEnrollmentDeviceDisconnected(BluetoothDevice device) {
- LOG.d("Bluetooth device " + device.getName() + "has been disconnected");
- mBluetoothDevice = null;
- }
-
- @Override
- public void onEnrollmentAdvertisingStarted() {
- LOG.d("Advertising started successfully");
- }
-
- @Override
- public void onEnrollmentAdvertisingFailed() {
- getFragmentController().goBack();
- }
- };
-
- @VisibleForTesting
- final ConfirmPairingCodeDialog.ConfirmPairingCodeListener mConfirmParingCodeListener =
- new ConfirmPairingCodeDialog.ConfirmPairingCodeListener() {
- public void onConfirmPairingCode() {
- try {
- mCarTrustAgentEnrollmentManager.enrollmentHandshakeAccepted(
- mBluetoothDevice);
- } catch (CarNotConnectedException e) {
- LOG.e(e.getMessage(), e);
- }
- }
-
- public void onDialogCancelled() {
- getFragmentController().goBack();
- }
- };
+ private CarUserManagerHelper mCarUserManagerHelper;
+ private LockPatternUtils mLockPatternUtils;
public AddTrustedDevicePreferenceController(Context context, String preferenceKey,
FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
- mCar = Car.createCar(context);
mCarUserManagerHelper = new CarUserManagerHelper(context);
mLockPatternUtils = new LockPatternUtils(context);
- try {
- mCarTrustAgentEnrollmentManager = (CarTrustAgentEnrollmentManager) mCar.getCarManager(
- Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE);
- } catch (CarNotConnectedException e) {
- LOG.e(e.getMessage(), e);
- }
- }
-
- @Override
- protected void checkInitialized() {
- if (mCarTrustAgentEnrollmentManager == null) {
- throw new IllegalStateException("mCarTrustAgentEnrollmentManager is null.");
- }
}
@Override
@@ -178,31 +56,4 @@
protected Class<Preference> getPreferenceType() {
return Preference.class;
}
-
- @Override
- public boolean handlePreferenceClicked(Preference preference) {
- try {
- mCarTrustAgentEnrollmentManager.startEnrollmentAdvertising();
- } catch (CarNotConnectedException e) {
- LOG.e(e.getMessage(), e);
- }
- // return false to make sure AddTrustedDeviceProgressFragment will show up.
- return false;
- }
-
- @Override
- protected void onStartInternal() {
- try {
- mCarTrustAgentEnrollmentManager.setEnrollmentCallback(mCarTrustAgentEnrollmentCallback);
- mCarTrustAgentEnrollmentManager.setBleCallback(mCarTrustAgentBleCallback);
- } catch (CarNotConnectedException e) {
- LOG.e(e.getMessage(), e);
- }
- ConfirmPairingCodeDialog pairingCodeDialog =
- (ConfirmPairingCodeDialog) getFragmentController().findDialogByTag(
- ConfirmPairingCodeDialog.TAG);
- if (pairingCodeDialog != null) {
- pairingCodeDialog.setConfirmPairingCodeListener(mConfirmParingCodeListener);
- }
- }
}
diff --git a/src/com/android/car/settings/security/CheckLockActivity.java b/src/com/android/car/settings/security/CheckLockActivity.java
index 8881e31..1725c9c 100644
--- a/src/com/android/car/settings/security/CheckLockActivity.java
+++ b/src/com/android/car/settings/security/CheckLockActivity.java
@@ -16,64 +16,26 @@
package com.android.car.settings.security;
-import android.app.admin.DevicePolicyManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.android.car.settings.common.CarSettingActivity;
-import com.android.car.settings.common.Logger;
-import com.android.internal.widget.LockPatternUtils;
/**
* Prompts the user to enter their pin, password, or pattern lock (if set) and returns
* {@link #RESULT_OK} on a successful entry or immediately if the user has no lock setup.
*/
public class CheckLockActivity extends CarSettingActivity implements CheckLockListener {
-
- private static final Logger LOG = new Logger(CheckLockActivity.class);
-
@Override
@Nullable
protected Fragment getFragment() {
- Fragment fragment;
- int passwordQuality = new LockPatternUtils(this).getKeyguardStoredPasswordQuality(
- UserHandle.myUserId());
- switch (passwordQuality) {
- case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
- // User has not set a password.
- setResult(RESULT_OK);
- finish();
- return null;
- case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- fragment = ConfirmLockPatternFragment.newInstance(
- /* isInSetupWizard= */ false);
- break;
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
- fragment = ConfirmLockPinPasswordFragment.newPinInstance(
- /* isInSetupWizard= */ false);
- break;
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
- fragment = ConfirmLockPinPasswordFragment.newPasswordInstance(
- /* isInSetupWizard= */ false);
- break;
- default:
- LOG.e("Unexpected password quality: " + String.valueOf(passwordQuality));
- fragment = ConfirmLockPinPasswordFragment.newPasswordInstance(
- /* isInSetupWizard= */ false);
+ Fragment lockFragment = ConfirmPasswordFragmentFactory.getFragment(/* context= */ this);
+ if (lockFragment == null) {
+ // User has not set a password
+ setResult(RESULT_OK);
+ finish();
}
-
- Bundle bundle = fragment.getArguments();
- if (bundle == null) {
- bundle = new Bundle();
- }
- bundle.putInt(ChooseLockTypeFragment.EXTRA_CURRENT_PASSWORD_QUALITY, passwordQuality);
- fragment.setArguments(bundle);
- return fragment;
+ return lockFragment;
}
@Override
diff --git a/src/com/android/car/settings/security/ConfirmPasswordFragmentFactory.java b/src/com/android/car/settings/security/ConfirmPasswordFragmentFactory.java
new file mode 100644
index 0000000..25bd784
--- /dev/null
+++ b/src/com/android/car/settings/security/ConfirmPasswordFragmentFactory.java
@@ -0,0 +1,79 @@
+/*
+ * 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.car.settings.security;
+
+import android.app.admin.DevicePolicyManager;
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.android.car.settings.common.Logger;
+import com.android.internal.widget.LockPatternUtils;
+
+/**
+ * Factory class which generate password fragment for current user.
+ */
+public class ConfirmPasswordFragmentFactory {
+
+ private static final Logger LOG = new Logger(ConfirmPasswordFragmentFactory.class);
+
+ /**
+ * Gets the correct password fragment of current user, returns the corresponding password
+ * fragment of current user
+ *
+ * @return {@code null} if no password is set for the current user.
+ */
+ @Nullable
+ public static Fragment getFragment(Context context) {
+ Fragment fragment;
+ int passwordQuality = new LockPatternUtils(context).getKeyguardStoredPasswordQuality(
+ new CarUserManagerHelper(context).getCurrentProcessUserId());
+ switch (passwordQuality) {
+ case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+ // User has not set a password.
+ return null;
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ fragment = ConfirmLockPatternFragment.newInstance(
+ /* isInSetupWizard= */ false);
+ break;
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ fragment = ConfirmLockPinPasswordFragment.newPinInstance(
+ /* isInSetupWizard= */ false);
+ break;
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ fragment = ConfirmLockPinPasswordFragment.newPasswordInstance(
+ /* isInSetupWizard= */ false);
+ break;
+ default:
+ LOG.e("Unexpected password quality: " + passwordQuality);
+ fragment = ConfirmLockPinPasswordFragment.newPasswordInstance(
+ /* isInSetupWizard= */ false);
+ }
+ Bundle bundle = fragment.getArguments();
+ if (bundle == null) {
+ bundle = new Bundle();
+ }
+ bundle.putInt(ChooseLockTypeFragment.EXTRA_CURRENT_PASSWORD_QUALITY, passwordQuality);
+ fragment.setArguments(bundle);
+ return fragment;
+ }
+}
diff --git a/tests/robotests/src/com/android/car/settings/security/AddTrustedDeviceActivityTest.java b/tests/robotests/src/com/android/car/settings/security/AddTrustedDeviceActivityTest.java
new file mode 100644
index 0000000..422e4bc
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/security/AddTrustedDeviceActivityTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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.car.settings.security;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.car.Car;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.CarUxRestrictionsManager;
+import android.car.trust.CarTrustAgentEnrollmentManager;
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.R;
+import com.android.car.settings.testutils.ShadowCar;
+import com.android.car.settings.testutils.ShadowLockPatternUtils;
+import com.android.internal.widget.LockPatternUtils;
+
+import org.junit.After;
+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;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+
+/**
+ * Unit tests for {@link AddTrustedDeviceActivity}.
+ */
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowCar.class, ShadowLockPatternUtils.class})
+public class AddTrustedDeviceActivityTest {
+ private static final String ADDRESS = "00:11:22:33:AA:BB";
+ private Context mContext;
+ private ActivityController<AddTrustedDeviceActivity> mActivityController;
+ private AddTrustedDeviceActivity mActivity;
+ @Mock
+ private CarTrustAgentEnrollmentManager mMockCarTrustAgentEnrollmentManager;
+ @Mock
+ private CarUxRestrictionsManager mMockCarUxRestrictionsManager;
+ @Mock
+ private LockPatternUtils mLockPatternUtils;
+ private CarUserManagerHelper mCarUserManagerHelper;
+ private BluetoothDevice mBluetoothDevice;
+ private static final String BLUETOOTH_DEVICE_KEY = "bluetoothDevice";
+ private static final String CURRENT_HANDLE_KEY = "currentHandle";
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ CarUxRestrictions noSetupRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
+ CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* time= */ 0).build();
+ when(mMockCarUxRestrictionsManager.getCurrentCarUxRestrictions())
+ .thenReturn(noSetupRestrictions);
+ ShadowCar.setCarManager(Car.CAR_UX_RESTRICTION_SERVICE, mMockCarUxRestrictionsManager);
+ ShadowLockPatternUtils.setInstance(mLockPatternUtils);
+ mContext = RuntimeEnvironment.application;
+ ShadowCar.setCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE,
+ mMockCarTrustAgentEnrollmentManager);
+ mCarUserManagerHelper = new CarUserManagerHelper(mContext);
+ mBluetoothDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(ADDRESS);
+ mActivityController = ActivityController.of(new AddTrustedDeviceActivity());
+ mActivity = mActivityController.get();
+ when(mLockPatternUtils.getKeyguardStoredPasswordQuality(
+ mCarUserManagerHelper.getCurrentProcessUserId())).thenReturn(
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+ mActivityController.create();
+ }
+
+ @After
+ public void tearDown() {
+ ShadowCar.reset();
+ ShadowLockPatternUtils.reset();
+ }
+
+ @Test
+ public void onStart_no_saveInstanceState_startAdvertising() {
+ mActivityController.start();
+ verify(mMockCarTrustAgentEnrollmentManager).startEnrollmentAdvertising();
+ }
+
+ @Test
+ public void onStart_saveInstanceState_deviceConnected_doNotStartAdvertising() {
+ // Recreate with saved state (e.g. during config change).
+ Bundle outState = new Bundle();
+ outState.putParcelable(BLUETOOTH_DEVICE_KEY, mBluetoothDevice);
+ mActivityController = ActivityController.of(new AddTrustedDeviceActivity());
+ mActivityController.setup(outState);
+ verify(mMockCarTrustAgentEnrollmentManager, never()).startEnrollmentAdvertising();
+ }
+
+ @Test
+ public void onStart_saveInstanceState_deviceNotConnected_startAdvertising() {
+ // Recreate with saved state (e.g. during config change).
+ Bundle outState = new Bundle();
+ outState.putParcelable(BLUETOOTH_DEVICE_KEY, null);
+ mActivityController = ActivityController.of(new AddTrustedDeviceActivity());
+ mActivityController.setup(outState);
+ verify(mMockCarTrustAgentEnrollmentManager).startEnrollmentAdvertising();
+ }
+
+ @Test
+ public void onStart_has_activated_handle_finish() {
+ mActivityController.start().postCreate(null).resume();
+ ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback> callBack =
+ ArgumentCaptor.forClass(
+ CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback.class);
+ verify(mMockCarTrustAgentEnrollmentManager).setEnrollmentCallback(callBack.capture());
+
+ callBack.getValue().onEscrowTokenAdded(1);
+ mActivityController.stop();
+
+ when(mMockCarTrustAgentEnrollmentManager.isEscrowTokenActive(1,
+ mCarUserManagerHelper.getCurrentProcessUserId())).thenReturn(true);
+ Bundle outState = new Bundle();
+ outState.putLong(CURRENT_HANDLE_KEY, 1);
+ outState.putParcelable(BLUETOOTH_DEVICE_KEY, mBluetoothDevice);
+ mActivityController = ActivityController.of(new AddTrustedDeviceActivity());
+ mActivityController.setup(outState).start();
+
+ assertThat(mActivityController.get().isFinishing()).isTrue();
+ }
+
+ @Test
+ public void onAuthStringAvailable_createDialog() {
+ mActivityController.start().postCreate(null).resume();
+ ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback>
+ enrollmentCallBack =
+ ArgumentCaptor.forClass(
+ CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback.class);
+ verify(mMockCarTrustAgentEnrollmentManager).setEnrollmentCallback(
+ enrollmentCallBack.capture());
+ enrollmentCallBack.getValue().onAuthStringAvailable(mBluetoothDevice, "123");
+
+ assertThat(mActivity.findDialogByTag(ConfirmPairingCodeDialog.TAG)).isNotNull();
+ }
+
+ @Test
+ public void onLockVerified_showAddTrustedDeviceProgressFragment() {
+ mActivityController.start().postCreate(null).resume();
+
+ mActivity.launchFragment(ConfirmLockPinPasswordFragment.newPinInstance(false));
+ mActivity.onLockVerified("lock".getBytes());
+
+ assertThat(mActivity.getSupportFragmentManager().findFragmentById(R.id.fragment_container))
+ .isInstanceOf(AddTrustedDeviceProgressFragment.class);
+ }
+
+ @Test
+ public void onEscrowTokenAdded_showCheckLockFragment() {
+ mActivityController.start().postCreate(null).resume();
+ ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback> callBack =
+ ArgumentCaptor.forClass(
+ CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback.class);
+ verify(mMockCarTrustAgentEnrollmentManager).setEnrollmentCallback(callBack.capture());
+
+ callBack.getValue().onEscrowTokenAdded(1);
+
+ assertThat(mActivityController.get().getFragment()).isInstanceOf(
+ ConfirmLockPinPasswordFragment.class);
+ }
+
+ @Test
+ public void onBluetoothDeviceDisconnected_finish() {
+ mActivityController.start().postCreate(null).resume();
+ ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback>
+ bleCallBack = ArgumentCaptor.forClass(
+ CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
+ verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(bleCallBack.capture());
+
+ bleCallBack.getValue().onBleEnrollmentDeviceDisconnected(mBluetoothDevice);
+
+ assertThat(mActivity.isFinishing()).isTrue();
+ }
+
+ @Test
+ public void onPairingCodeDialogConfirmed_handshakeAccepted() {
+ mActivityController.start().postCreate(null).resume();
+ ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback> bleCallBack =
+ ArgumentCaptor.forClass(
+ CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
+ verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(bleCallBack.capture());
+
+ bleCallBack.getValue().onBleEnrollmentDeviceConnected(mBluetoothDevice);
+ mActivity.mConfirmParingCodeListener.onConfirmPairingCode();
+ verify(mMockCarTrustAgentEnrollmentManager).enrollmentHandshakeAccepted(mBluetoothDevice);
+
+ }
+
+ @Test
+ public void onStart_onEscrowTokenActiveStateChanged_activated_finish() {
+ mActivityController.start().postCreate(null).resume();
+ // Recreate with saved state (e.g. during config change).
+ ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback> callBack =
+ ArgumentCaptor.forClass(
+ CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback.class);
+ verify(mMockCarTrustAgentEnrollmentManager).setEnrollmentCallback(callBack.capture());
+
+ ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback> bleCallBack =
+ ArgumentCaptor.forClass(
+ CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
+ verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(bleCallBack.capture());
+
+ bleCallBack.getValue().onBleEnrollmentDeviceConnected(mBluetoothDevice);
+ callBack.getValue().onEscrowTokenActiveStateChanged(1, true);
+
+ assertThat(mActivity.isFinishing()).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/car/settings/security/AddTrustedDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/security/AddTrustedDevicePreferenceControllerTest.java
index 9257279..5447dd1 100644
--- a/tests/robotests/src/com/android/car/settings/security/AddTrustedDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/car/settings/security/AddTrustedDevicePreferenceControllerTest.java
@@ -18,18 +18,10 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.trust.CarTrustAgentEnrollmentManager;
import android.car.userlib.CarUserManagerHelper;
import android.content.Context;
@@ -38,7 +30,6 @@
import com.android.car.settings.CarSettingsRobolectricTestRunner;
import com.android.car.settings.common.PreferenceControllerTestHelper;
-import com.android.car.settings.testutils.ShadowCar;
import com.android.car.settings.testutils.ShadowLockPatternUtils;
import com.android.internal.widget.LockPatternUtils;
@@ -46,40 +37,31 @@
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;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
/**
* Unit tests for {@link AddTrustedDevicePreferenceController}.
*/
@RunWith(CarSettingsRobolectricTestRunner.class)
-@Config(shadows = {ShadowCar.class, ShadowLockPatternUtils.class})
+@Config(shadows = {ShadowLockPatternUtils.class})
public class AddTrustedDevicePreferenceControllerTest {
-
- private static final String ADDRESS = "00:11:22:33:AA:BB";
private Context mContext;
private PreferenceControllerTestHelper<AddTrustedDevicePreferenceController>
mPreferenceControllerHelper;
@Mock
- private CarTrustAgentEnrollmentManager mMockCarTrustAgentEnrollmentManager;
- @Mock
private LockPatternUtils mLockPatternUtils;
private Preference mPreference;
private AddTrustedDevicePreferenceController mController;
private CarUserManagerHelper mCarUserManagerHelper;
- private BluetoothDevice mBluetoothDevice;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
- ShadowCar.setCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE,
- mMockCarTrustAgentEnrollmentManager);
ShadowLockPatternUtils.setInstance(mLockPatternUtils);
mPreference = new Preference(mContext);
mPreferenceControllerHelper = new PreferenceControllerTestHelper<>(mContext,
@@ -87,122 +69,21 @@
mController = mPreferenceControllerHelper.getController();
mCarUserManagerHelper = new CarUserManagerHelper(mContext);
mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
- mBluetoothDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(ADDRESS);
}
@After
public void tearDown() {
- ShadowCar.reset();
ShadowLockPatternUtils.reset();
}
@Test
- public void onPreferenceClicked_hasPassword_startAdvertising() throws CarNotConnectedException {
+ public void refreshUi_hasPassword_preferenceEnabled() {
when(mLockPatternUtils.getKeyguardStoredPasswordQuality(
mCarUserManagerHelper.getCurrentProcessUserId())).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
mController.refreshUi();
- mPreference.performClick();
-
- verify(mMockCarTrustAgentEnrollmentManager).startEnrollmentAdvertising();
- }
-
- @Test
- public void onAuthStringAvailable_showDialog() throws CarNotConnectedException {
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback>
- enrollmentCallBack =
- ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setEnrollmentCallback(
- enrollmentCallBack.capture());
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback> bleCallBack =
- ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(bleCallBack.capture());
-
- bleCallBack.getValue().onBleEnrollmentDeviceConnected(mBluetoothDevice);
- enrollmentCallBack.getValue().onAuthStringAvailable(mBluetoothDevice, "123");
-
- verify(mPreferenceControllerHelper.getMockFragmentController()).showDialog(
- any(ConfirmPairingCodeDialog.class), anyString());
- }
-
- @Test
- public void onEscrowTokenActiveStateChanged_returnToListFragment()
- throws CarNotConnectedException {
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback> callBack =
- ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setEnrollmentCallback(callBack.capture());
-
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback>
- bleCallBack = ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(bleCallBack.capture());
-
- bleCallBack.getValue().onBleEnrollmentDeviceConnected(mBluetoothDevice);
- callBack.getValue().onEscrowTokenActiveStateChanged(123, true);
-
- verify(mPreferenceControllerHelper.getMockFragmentController()).goBack();
- }
-
- @Test
- public void onEnrollmentAdvertisingFailed_returnToListFragment()
- throws CarNotConnectedException {
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback> callBack =
- ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(callBack.capture());
-
- callBack.getValue().onEnrollmentAdvertisingFailed();
-
- verify(mPreferenceControllerHelper.getMockFragmentController()).goBack();
- }
-
- @Test
- public void onEscrowTokenAdded_startCheckLockActivity()
- throws CarNotConnectedException {
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback> callBack =
- ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setEnrollmentCallback(callBack.capture());
-
- callBack.getValue().onEscrowTokenAdded(1);
-
- assertThat(ShadowApplication.getInstance().getNextStartedActivity().getComponent()
- .getClassName()).isEqualTo(CheckLockActivity.class.getName());
- }
-
- @Test
- public void onBluetoothDeviceConnected_initiateHandshake() throws CarNotConnectedException {
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback>
- bleCallBack = ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(bleCallBack.capture());
-
- bleCallBack.getValue().onBleEnrollmentDeviceConnected(mBluetoothDevice);
- }
-
- @Test
- public void onPairingCodeDialogConfirmed_handShakeAccepted()
- throws CarNotConnectedException {
- ArgumentCaptor<CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback>
- bleCallBack = ArgumentCaptor.forClass(
- CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback.class);
- verify(mMockCarTrustAgentEnrollmentManager).setBleCallback(bleCallBack.capture());
-
- bleCallBack.getValue().onBleEnrollmentDeviceConnected(mBluetoothDevice);
- mController.mConfirmParingCodeListener.onConfirmPairingCode();
-
- verify(mMockCarTrustAgentEnrollmentManager).enrollmentHandshakeAccepted(mBluetoothDevice);
-
- }
-
- @Test
- public void onPairingCodeDialogCancelled_returnToListFragment() {
- mController.mConfirmParingCodeListener.onDialogCancelled();
- verify(mPreferenceControllerHelper.getMockFragmentController()).goBack();
+ assertThat(mPreference.isEnabled()).isTrue();
}
@Test
diff --git a/tests/robotests/src/com/android/car/settings/security/TrustedDeviceListPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/security/TrustedDeviceListPreferenceControllerTest.java
index b130812..8bb8710 100644
--- a/tests/robotests/src/com/android/car/settings/security/TrustedDeviceListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/car/settings/security/TrustedDeviceListPreferenceControllerTest.java
@@ -53,6 +53,7 @@
import org.robolectric.annotation.Config;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -72,6 +73,7 @@
private CarUserManagerHelper mCarUserManagerHelper;
private PreferenceGroup mPreferenceGroup;
private TrustedDeviceListPreferenceController mController;
+
private TrustedDeviceInfo mTestDevice1 = new TrustedDeviceInfo(1, "", "");
private TrustedDeviceInfo mTestDevice2 = new TrustedDeviceInfo(2, "", "");
private TrustedDeviceInfo mTestDevice3 = new TrustedDeviceInfo(3, "", "");
@@ -158,7 +160,8 @@
mCarUserManagerHelper.getCurrentProcessUserId())).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
when(mMockCarTrustAgentEnrollmentManager.getEnrolledDeviceInfoForUser(
- mCarUserManagerHelper.getCurrentProcessUserId())).thenReturn(new ArrayList<>());
+ mCarUserManagerHelper.getCurrentProcessUserId())).thenReturn(
+ Collections.emptyList());
mController.refreshUi();