Merge changes from topic "aae-carwatchdog-server"

* changes:
  Add sepolicy for car watchdog
  Initial implementation of car watchdog server
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index 5580745..1bbde70 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -1219,7 +1219,7 @@
 package android.car.user {
 
   public final class CarUserManager {
-    method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void addListener(@NonNull android.car.user.CarUserManager.UserLifecycleListener);
+    method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void addListener(@NonNull java.util.concurrent.Executor, @NonNull android.car.user.CarUserManager.UserLifecycleListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void removeListener(@NonNull android.car.user.CarUserManager.UserLifecycleListener);
     field public static final int USER_LIFECYCLE_EVENT_TYPE_STARTING = 1; // 0x1
     field public static final int USER_LIFECYCLE_EVENT_TYPE_STOPPED = 5; // 0x5
diff --git a/car-lib/api/test-current.txt b/car-lib/api/test-current.txt
index b0d948e..27a9e3d 100644
--- a/car-lib/api/test-current.txt
+++ b/car-lib/api/test-current.txt
@@ -52,7 +52,7 @@
 package android.car.user {
 
   public final class CarUserManager {
-    method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void addListener(@NonNull android.car.user.CarUserManager.UserLifecycleListener);
+    method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void addListener(@NonNull java.util.concurrent.Executor, @NonNull android.car.user.CarUserManager.UserLifecycleListener);
     method public int createUser(@Nullable String);
     method public static String lifecycleEventTypeToString(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void removeListener(@NonNull android.car.user.CarUserManager.UserLifecycleListener);
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index 11aa3b9..bfec3da 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -63,6 +63,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.TransactionTooLargeException;
@@ -1538,12 +1539,19 @@
             return;
         } else if (mContext instanceof Service) {
             Service service = (Service) mContext;
-            throw new IllegalStateException("Car service has crashed, client not handle it:"
-                    + service.getPackageName() + "," + service.getClass().getSimpleName(),
-                    mConstructionStack);
+            killClient(service.getPackageName() + "," + service.getClass().getSimpleName());
+        } else {
+            killClient(/* clientInfo= */ null);
         }
-        throw new IllegalStateException("Car service crashed, client not handling it.",
+    }
+
+    private void killClient(@Nullable String clientInfo) {
+        Log.w(TAG_CAR, "**Car service has crashed. Client(" + clientInfo + ") is not handling it."
+                        + " Client should use Car.createCar(..., CarServiceLifecycleListener, .."
+                        + ".) to handle it properly. Check pritned callstack to check where other "
+                        + "version of Car.createCar() was called. Killing the client process**",
                 mConstructionStack);
+        Process.killProcess(Process.myPid());
     }
 
     /** @hide */
diff --git a/car-lib/src/android/car/user/CarUserManager.java b/car-lib/src/android/car/user/CarUserManager.java
index c00a425..64c4388 100644
--- a/car-lib/src/android/car/user/CarUserManager.java
+++ b/car-lib/src/android/car/user/CarUserManager.java
@@ -21,6 +21,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Process.myUid;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -38,7 +39,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.util.ArraySet;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -50,6 +51,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * API to manage users related to car.
@@ -138,7 +140,7 @@
 
     @Nullable
     @GuardedBy("mLock")
-    private ArraySet<UserLifecycleListener> mListeners;
+    private ArrayMap<UserLifecycleListener, Executor> mListeners;
 
     @Nullable
     @GuardedBy("mLock")
@@ -291,10 +293,12 @@
     @SystemApi
     @TestApi
     @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
-    public void addListener(@NonNull UserLifecycleListener listener) {
+    public void addListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull UserLifecycleListener listener) {
         checkInteractAcrossUsersPermission();
 
         // TODO(b/144120654): add unit tests to validate input
+        // - executor cannot be null
         // - listener cannot be null
         // - listener must not be added before
 
@@ -312,10 +316,10 @@
             }
 
             if (mListeners == null) {
-                mListeners = new ArraySet<>(1); // Most likely app will have just one listener
+                mListeners = new ArrayMap<>(1); // Most likely app will have just one listener
             }
             if (DBG) Log.d(TAG, "Adding listener: " + listener);
-            mListeners.add(listener);
+            mListeners.put(listener, executor);
         }
     }
 
@@ -395,7 +399,7 @@
             UserHandle fromHandle = resultData.getParcelable(BUNDLE_PARAM_PREVIOUS_USER_HANDLE);
             int eventType = resultData.getInt(BUNDLE_PARAM_ACTION);
             UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromHandle, toHandle);
-            ArraySet<UserLifecycleListener> listeners;
+            ArrayMap<UserLifecycleListener, Executor> listeners;
             synchronized (mLock) {
                 listeners = mListeners;
             }
@@ -404,9 +408,10 @@
                 return;
             }
             for (int i = 0; i < listeners.size(); i++) {
-                UserLifecycleListener listener = listeners.valueAt(i);
+                UserLifecycleListener listener = listeners.keyAt(i);
+                Executor executor = listeners.valueAt(i);
                 if (DBG) Log.d(TAG, "Calling listener " + listener + " for event " + event);
-                listener.onEvent(event);
+                executor.execute(() -> listener.onEvent(event));
             }
         }
     }
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/config.xml b/car_product/overlay/frameworks/base/core/res/res/values/config.xml
index 4e504f9..26f81b4 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values/config.xml
@@ -48,7 +48,6 @@
     <!-- Allow smart unlock immediately after boot because the user shouldn't have to enter a pin
          code to unlock their car head unit. -->
     <bool name="config_strongAuthRequiredOnBoot">false</bool>
-    <string name="config_defaultTrustAgent" translatable="false">com.android.car/com.android.car.trust.CarBleTrustAgent</string>
     <!-- Show Navigation Bar -->
     <bool name="config_showNavigationBar">true</bool>
 
diff --git a/computepipe/tests/PipeQueryTest.cpp b/computepipe/tests/PipeQueryTest.cpp
index 3a03391..634ebd0 100644
--- a/computepipe/tests/PipeQueryTest.cpp
+++ b/computepipe/tests/PipeQueryTest.cpp
@@ -106,7 +106,7 @@
     addFakeRunner("dummy2", dummy2);
 
     std::vector<std::string>* outNames = new std::vector<std::string>();
-    std::unique_ptr<PipeQuery> qIface = std::make_unique<PipeQuery>(mRegistry);
+    std::shared_ptr<PipeQuery> qIface = ndk::SharedRefBase::make<PipeQuery>(mRegistry);
     ASSERT_TRUE(qIface->getGraphList(outNames).isOk());
 
     ASSERT_NE(outNames->size(), 0);
@@ -121,7 +121,7 @@
     std::shared_ptr<IPipeRunner> dummy1 = ndk::SharedRefBase::make<FakeRunner>();
     addFakeRunner("dummy1", dummy1);
 
-    std::unique_ptr<PipeQuery> qIface = std::make_unique<PipeQuery>(mRegistry);
+    std::shared_ptr<PipeQuery> qIface = ndk::SharedRefBase::make<PipeQuery>(mRegistry);
     std::shared_ptr<IClientInfo> info = ndk::SharedRefBase::make<FakeClientInfo>();
     std::shared_ptr<IPipeRunner> runner;
     ASSERT_TRUE(qIface->getPipeRunner("dummy1", info, &runner).isOk());
diff --git a/evs/apps/default/config.json b/evs/apps/default/config.json
index 0d968f5..b7fbd94 100644
--- a/evs/apps/default/config.json
+++ b/evs/apps/default/config.json
@@ -15,7 +15,7 @@
   },
   "cameras" : [
     {
-      "cameraId" : "/dev/video1",
+      "cameraId" : "/dev/video3",
       "function" : "reverse, park",
       "x" : 0.0,
       "y" : -40.0,
diff --git a/evs/sampleDriver/resources/evs_sample_configuration.xml b/evs/sampleDriver/resources/evs_sample_configuration.xml
index 35f264e..fa3ada3 100644
--- a/evs/sampleDriver/resources/evs_sample_configuration.xml
+++ b/evs/sampleDriver/resources/evs_sample_configuration.xml
@@ -55,13 +55,13 @@
                     name='LOGICAL_MULTI_CAMERA_PHYSICAL_IDS'
                     type='byte[]'
                     size='2'
-                    value='/dev/video1,/dev/video2'
+                    value='/dev/video3,/dev/video4'
                 />
             </characteristics>
         </group>
 
         <!-- camera device starts -->
-        <device id='/dev/video1' position='rear'>
+        <device id='/dev/video3' position='rear'>
             <caps>
                 <!-- list of supported controls -->
                 <supported_controls>
@@ -129,7 +129,7 @@
                 />
             </characteristics>
         </device>
-        <device id='/dev/video2' position='front'>
+        <device id='/dev/video4' position='front'>
             <caps>
                 <!-- list of supported controls -->
                 <supported_controls>
diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te
index 87bcd4d..179623d 100644
--- a/evs/sepolicy/evs_driver.te
+++ b/evs/sepolicy/evs_driver.te
@@ -1,10 +1,10 @@
 # evs_mock mock hardware driver service
-type hal_evs_driver, domain, coredomain;
+type hal_evs_driver, domain;
 hal_server_domain(hal_evs_driver, hal_evs)
 hal_client_domain(hal_evs_driver, hal_evs)
 
 # allow init to launch processes in this context
-type hal_evs_driver_exec, exec_type, file_type, system_file_type;
+type hal_evs_driver_exec, exec_type, file_type, vendor_file_type;
 init_daemon_domain(hal_evs_driver)
 binder_use(hal_evs_driver)
 
diff --git a/evs/sepolicy/file_contexts b/evs/sepolicy/file_contexts
index 0ce34d1..7b8ec19 100644
--- a/evs/sepolicy/file_contexts
+++ b/evs/sepolicy/file_contexts
@@ -3,10 +3,10 @@
 # Binaries associated with the default EVS stack, plus
 # the directory which contains the configuration for the evs_app
 #
-/system/bin/android\.hardware\.automotive\.evs@1\.[0-9]+-sample u:object_r:hal_evs_driver_exec:s0
 /system/bin/android\.automotive\.evs\.manager@1\.[0-9]+         u:object_r:evs_manager_exec:s0
 /system/bin/evs_app                                             u:object_r:evs_app_exec:s0
 /system/bin/evs_app_support_lib                                 u:object_r:evs_app_exec:s0
 /system/etc/automotive/evs(/.*)?                                u:object_r:evs_app_files:s0
+/vendor/bin/android\.hardware\.automotive\.evs@1\.[0-9]+-sample u:object_r:hal_evs_driver_exec:s0
 
 ###################################
diff --git a/service/src/com/android/car/CarPowerManagementService.java b/service/src/com/android/car/CarPowerManagementService.java
index 7662bcc..77d543e 100644
--- a/service/src/com/android/car/CarPowerManagementService.java
+++ b/service/src/com/android/car/CarPowerManagementService.java
@@ -33,6 +33,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -107,6 +108,8 @@
     private boolean mIsBooting = true;
     @GuardedBy("mLock")
     private boolean mIsResuming;
+    @GuardedBy("mLock")
+    private boolean mRebootAfterGarageMode;
     private final boolean mDisableUserSwitchDuringResume;
     private final CarUserManagerHelper mCarUserManagerHelper;
     private final UserManager mUserManager;    // CarUserManagerHelper is deprecated...
@@ -248,7 +251,8 @@
         writer.print(",mShutdownOnNextSuspend:" + mShutdownOnNextSuspend);
         writer.print(",mShutdownOnFinish:" + mShutdownOnFinish);
         writer.print(",sShutdownPrepareTimeMs:" + sShutdownPrepareTimeMs);
-        writer.println(",mDisableUserSwitchDuringResume:" + mDisableUserSwitchDuringResume);
+        writer.print(",mDisableUserSwitchDuringResume:" + mDisableUserSwitchDuringResume);
+        writer.println(",mRebootAfterGarageMode:" + mRebootAfterGarageMode);
     }
 
     @Override
@@ -539,8 +543,21 @@
             simulatedMode = mInSimulatedDeepSleepMode;
         }
         boolean mustShutDown;
+        boolean forceReboot;
         synchronized (mLock) {
             mustShutDown = mShutdownOnFinish && !simulatedMode;
+            forceReboot = mRebootAfterGarageMode;
+            mRebootAfterGarageMode = false;
+        }
+        if (forceReboot) {
+            PowerManager powerManager = mContext.getSystemService(PowerManager.class);
+            if (powerManager == null) {
+                Log.wtf(CarLog.TAG_POWER, "No PowerManager. Cannot reboot.");
+            } else {
+                Log.i(CarLog.TAG_POWER, "GarageMode has completed. Forcing reboot.");
+                powerManager.reboot("GarageModeReboot");
+                throw new AssertionError("Should not return from PowerManager.reboot()");
+            }
         }
         if (mustShutDown) {
             // shutdown HU
@@ -1119,18 +1136,23 @@
     }
 
     /**
-     * Manually enter simulated suspend (Deep Sleep) mode
-     * Invoked using "adb shell dumpsys activity service com.android.car suspend".
+     * Manually enter simulated suspend (Deep Sleep) mode, trigging Garage mode.
+     * If the parameter is 'true', reboot the system when Garage Mode completes.
+     *
+     * Invoked using "adb shell dumpsys activity service com.android.car suspend" or
+     * "adb shell dumpsys activity service com.android.car garage-mode reboot".
      * This is similar to 'onApPowerStateChange()' except that it needs to create a CpmsState
      * that is not directly derived from a VehicleApPowerStateReq.
      */
-    public void forceSimulatedSuspend() {
+    @VisibleForTesting
+    void forceSuspendAndMaybeReboot(boolean shouldReboot) {
         synchronized (mSimulationWaitObject) {
             mInSimulatedDeepSleepMode = true;
             mWakeFromSimulatedSleep = false;
         }
         PowerHandler handler;
         synchronized (mLock) {
+            mRebootAfterGarageMode = shouldReboot;
             mPendingPowerStates.addFirst(new CpmsState(CpmsState.SIMULATE_SLEEP,
                                                        CarPowerStateListener.SHUTDOWN_PREPARE));
             handler = mHandler;
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index 62bc3b1..acd73ab 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -781,6 +781,7 @@
         private static final String PARAM_ON_MODE = "on";
         private static final String PARAM_OFF_MODE = "off";
         private static final String PARAM_QUERY_MODE = "query";
+        private static final String PARAM_REBOOT = "reboot";
 
         private static final int RESULT_OK = 0;
         private static final int RESULT_ERROR = -1; // Arbitrary value, any non-0 is fine
@@ -823,8 +824,9 @@
             pw.println("\t  Inject an error event from VHAL for testing.");
             pw.println("\tenable-uxr true|false");
             pw.println("\t  Enable/Disable UX restrictions and App blocking.");
-            pw.println("\tgarage-mode [on|off|query]");
-            pw.println("\t  Force into garage mode or check status.");
+            pw.println("\tgarage-mode [on|off|query|reboot]");
+            pw.println("\t  Force into or out of garage mode, or check status.");
+            pw.println("\t  With 'reboot', enter garage mode, then reboot when it completes.");
             pw.println("\tget-do-activities pkgname");
             pw.println("\t  Get Distraction Optimized activities in given package.");
             pw.println("\tget-carpropertyconfig [propertyId]");
@@ -846,7 +848,7 @@
             pw.println("\t--metrics");
             pw.println("\t  When used with dumpsys, only metrics will be in the dumpsys output.");
             pw.println("\tset-zoneid-for-uid [zoneid] [uid]");
-            pw.println("\t Maps the audio zoneid to uid.");
+            pw.println("\t  Maps the audio zoneid to uid.");
             pw.println("\tstart-fixed-activity displayId packageName activityName");
             pw.println("\t  Start an Activity the specified display as fixed mode");
             pw.println("\tstop-fixed-mode displayId");
@@ -981,7 +983,7 @@
                     writer.println("Resume: Simulating resuming from Deep Sleep");
                     break;
                 case COMMAND_SUSPEND:
-                    mCarPowerManagementService.forceSimulatedSuspend();
+                    mCarPowerManagementService.forceSuspendAndMaybeReboot(false);
                     writer.println("Resume: Simulating powering down to Deep Sleep");
                     break;
                 case COMMAND_ENABLE_TRUSTED_DEVICE:
@@ -1300,9 +1302,13 @@
                 case PARAM_QUERY_MODE:
                     mGarageModeService.dump(writer);
                     break;
+                case PARAM_REBOOT:
+                    mCarPowerManagementService.forceSuspendAndMaybeReboot(true);
+                    writer.println("Entering Garage Mode. Will reboot when it completes.");
+                    break;
                 default:
                     writer.println("Unknown value. Valid argument: " + PARAM_ON_MODE + "|"
-                            + PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE);
+                            + PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE + "|" + PARAM_REBOOT);
             }
         }
 
diff --git a/service/src/com/android/car/hal/PowerHalService.java b/service/src/com/android/car/hal/PowerHalService.java
index 09d1bd0..cc71d25 100644
--- a/service/src/com/android/car/hal/PowerHalService.java
+++ b/service/src/com/android/car/hal/PowerHalService.java
@@ -275,6 +275,10 @@
         } else if (brightness > 100) {
             brightness = 100;
         }
+        VehiclePropConfig prop = mProperties.get(DISPLAY_BRIGHTNESS);
+        if (prop == null) {
+            return;
+        }
         try {
             mHal.set(VehicleProperty.DISPLAY_BRIGHTNESS, 0).to(brightness);
             Log.i(CarLog.TAG_POWER, "send display brightness = " + brightness);
diff --git a/tests/CarDeveloperOptions/res/xml/accessibility_settings.xml b/tests/CarDeveloperOptions/res/xml/accessibility_settings.xml
index b170ca0..3c98a00 100644
--- a/tests/CarDeveloperOptions/res/xml/accessibility_settings.xml
+++ b/tests/CarDeveloperOptions/res/xml/accessibility_settings.xml
@@ -21,11 +21,6 @@
         android:title="@string/accessibility_settings"
         android:persistent="true">
 
-    <Preference
-            android:key="accessibility_shortcut_preference"
-            android:fragment="com.android.car.developeroptions.accessibility.AccessibilityShortcutPreferenceFragment"
-            android:title="@string/accessibility_global_gesture_preference_title"/>
-
     <PreferenceCategory
             android:key="user_installed_services_category"
             android:title="@string/user_installed_services_category_title">
diff --git a/tests/CarDeveloperOptions/src/com/android/car/developeroptions/accessibility/AccessibilitySettings.java b/tests/CarDeveloperOptions/src/com/android/car/developeroptions/accessibility/AccessibilitySettings.java
index df096bd..0c8b62c 100644
--- a/tests/CarDeveloperOptions/src/com/android/car/developeroptions/accessibility/AccessibilitySettings.java
+++ b/tests/CarDeveloperOptions/src/com/android/car/developeroptions/accessibility/AccessibilitySettings.java
@@ -52,16 +52,16 @@
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 
-import com.android.internal.accessibility.AccessibilityShortcutController;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.view.RotationPolicy;
-import com.android.internal.view.RotationPolicy.RotationPolicyListener;
 import com.android.car.developeroptions.R;
 import com.android.car.developeroptions.SettingsPreferenceFragment;
 import com.android.car.developeroptions.Utils;
 import com.android.car.developeroptions.display.DarkUIPreferenceController;
 import com.android.car.developeroptions.display.ToggleFontSizePreferenceFragment;
 import com.android.car.developeroptions.search.BaseSearchIndexProvider;
+import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.view.RotationPolicy;
+import com.android.internal.view.RotationPolicy.RotationPolicyListener;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
@@ -236,7 +236,6 @@
     private Preference mDisplayMagnificationPreferenceScreen;
     private Preference mFontSizePreferenceScreen;
     private Preference mAutoclickPreferenceScreen;
-    private Preference mAccessibilityShortcutPreferenceScreen;
     private Preference mDisplayDaltonizerPreferenceScreen;
     private Preference mHearingAidPreference;
     private Preference mVibrationPreferenceScreen;
@@ -514,9 +513,6 @@
         // Display color adjustments.
         mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN);
 
-        // Accessibility shortcut.
-        mAccessibilityShortcutPreferenceScreen = findPreference(ACCESSIBILITY_SHORTCUT_PREFERENCE);
-
         // Vibrations.
         mVibrationPreferenceScreen = findPreference(VIBRATION_PREFERENCE_SCREEN);
 
@@ -759,8 +755,6 @@
 
         updateAutoclickSummary(mAutoclickPreferenceScreen);
 
-        updateAccessibilityShortcut(mAccessibilityShortcutPreferenceScreen);
-
         updateAccessibilityTimeoutSummary(getContentResolver(),
                 findPreference(ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE));
         updateAccessibilityTimeoutSummary(getContentResolver(),
@@ -936,23 +930,6 @@
         mToggleMasterMonoPreference.setChecked(masterMono);
     }
 
-    private void updateAccessibilityShortcut(Preference preference) {
-        if (AccessibilityManager.getInstance(getActivity())
-                .getInstalledAccessibilityServiceList().isEmpty()) {
-            mAccessibilityShortcutPreferenceScreen
-                    .setSummary(getString(R.string.accessibility_no_services_installed));
-            mAccessibilityShortcutPreferenceScreen.setEnabled(false);
-        } else {
-            mAccessibilityShortcutPreferenceScreen.setEnabled(true);
-            boolean shortcutEnabled =
-                    AccessibilityUtils.isShortcutEnabled(getContext(), UserHandle.myUserId());
-            CharSequence summary = shortcutEnabled
-                    ? AccessibilityShortcutPreferenceFragment.getServiceName(getContext())
-                    : getString(R.string.accessibility_feature_state_off);
-            mAccessibilityShortcutPreferenceScreen.setSummary(summary);
-        }
-    }
-
     private static void configureMagnificationPreferenceIfNeeded(Preference preference) {
         // Some devices support only a single magnification mode. In these cases, we redirect to
         // the magnification mode's UI directly, rather than showing a PreferenceScreen with a
diff --git a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
index 1c7c9e9..7fb9066 100644
--- a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
+++ b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
@@ -21,10 +21,10 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.car.Car;
 import android.car.storagemonitoring.CarStorageMonitoringManager;
 import android.car.storagemonitoring.IoStats;
@@ -33,6 +33,7 @@
 import android.car.storagemonitoring.UidIoRecord;
 import android.car.storagemonitoring.WearEstimate;
 import android.car.storagemonitoring.WearEstimateChange;
+import android.content.Context;
 import android.content.Intent;
 import android.os.SystemClock;
 import android.util.JsonWriter;
@@ -58,7 +59,6 @@
 import org.junit.Test;
 import org.junit.rules.TestName;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 
 import java.io.File;
 import java.io.FileWriter;
@@ -308,8 +308,10 @@
 
     private CarStorageMonitoringManager mCarStorageMonitoringManager;
 
-    private ArgumentCaptor<Intent> mBroadcastIntentArg = ArgumentCaptor.forClass(Intent.class);
-    private ArgumentCaptor<String> mBroadcastStringArg = ArgumentCaptor.forClass(String.class);
+    @Override
+    protected MockedCarTestContext createMockedCarTestContext(Context context) {
+        return new CarStorageMonitoringTestContext(context);
+    }
 
     @Override
     protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
@@ -382,10 +384,7 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        doNothing().when(getCarServiceContext()).sendBroadcast(mBroadcastIntentArg.capture(),
-                mBroadcastStringArg.capture());
         mMockSystemStateInterface.executeBootCompletedActions();
-
         mCarStorageMonitoringManager =
             (CarStorageMonitoringManager) getCar().getCarManager(Car.STORAGE_MONITORING_SERVICE);
     }
@@ -656,7 +655,9 @@
         mMockStorageMonitoringInterface.addIoStatsRecord(record);
         mMockTimeInterface.setUptime(500).tick();
 
-        assertBroadcastArgs(mBroadcastIntentArg.getValue(), mBroadcastStringArg.getValue());
+        CarStorageMonitoringTestContext context = (CarStorageMonitoringTestContext) getContext();
+        assertBroadcastArgs(context.getLastBroadcastedIntent(),
+                context.getLastBroadcastedString());
     }
 
     @Test
@@ -678,7 +679,9 @@
         mMockStorageMonitoringInterface.addIoStatsRecord(record);
         mMockTimeInterface.setUptime(500).tick();
 
-        assertBroadcastArgs(mBroadcastIntentArg.getValue(), mBroadcastStringArg.getValue());
+        CarStorageMonitoringTestContext context = (CarStorageMonitoringTestContext) getContext();
+        assertBroadcastArgs(context.getLastBroadcastedIntent(),
+                context.getLastBroadcastedString());
     }
 
     @Test
@@ -773,6 +776,35 @@
 
     }
 
+    /**
+     * Special version of {@link MockedCarTestContext} that stores the last arguments used when
+     * invoking {@method sendBroadcast(Intent, String)} to be retrieved later by the test.
+     */
+    private class CarStorageMonitoringTestContext extends MockedCarTestContext {
+        private Intent mLastBroadcastedIntent;
+        private String mLastBroadcastedString;
+
+        CarStorageMonitoringTestContext(Context base) {
+            super(base);
+        }
+
+        @Override
+        public void sendBroadcast(@RequiresPermission Intent intent,
+                @Nullable String receiverPermission) {
+            mLastBroadcastedIntent = intent;
+            mLastBroadcastedString = receiverPermission;
+            super.sendBroadcast(intent, receiverPermission);
+        }
+
+        Intent getLastBroadcastedIntent() {
+            return mLastBroadcastedIntent;
+        }
+
+        String getLastBroadcastedString() {
+            return mLastBroadcastedString;
+        }
+    }
+
     static final class MockStorageMonitoringInterface implements StorageMonitoringInterface,
         WearInformationProvider {
         private WearInformation mWearInformation = null;
diff --git a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
index 50db8b4..cdff2ac 100644
--- a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
+++ b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
@@ -15,13 +15,10 @@
  */
 package com.android.car;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
 import android.annotation.NonNull;
@@ -30,6 +27,7 @@
 import android.car.test.CarTestManagerBinderWrapper;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.res.Resources;
@@ -108,6 +106,8 @@
     private static final IBinder mCarServiceToken = new Binder();
     private static boolean mRealCarServiceReleased = false;
 
+    private MockedCarTestContext mMockedCarTestContext;
+
     protected synchronized MockedVehicleHal createMockedVehicleHal() {
         return new MockedVehicleHal();
     }
@@ -146,8 +146,16 @@
                 new String[0]);
     }
 
-    protected Context getContext() {
-        return InstrumentationRegistry.getInstrumentation().getTargetContext();
+    protected synchronized Context getContext() {
+        if (mMockedCarTestContext == null) {
+            mMockedCarTestContext = createMockedCarTestContext(
+                    InstrumentationRegistry.getInstrumentation().getTargetContext());
+        }
+        return mMockedCarTestContext;
+    }
+
+    protected MockedCarTestContext createMockedCarTestContext(Context context) {
+        return new MockedCarTestContext(context);
     }
 
     protected Context getTestContext() {
@@ -186,11 +194,8 @@
         mFakeSystemInterface = getSystemInterfaceBuilder().build();
         configureFakeSystemInterface();
 
-        Context context = getCarServiceContext();
-        spyOn(context);
-        mResources = new MockResources(context.getResources());
-        configureResourceOverrides(mResources);
-        doReturn(mResources).when(context).getResources();
+        mMockedCarTestContext = (MockedCarTestContext) getContext();
+        configureResourceOverrides((MockResources) mMockedCarTestContext.getResources());
 
         doAnswer((invocation) -> {
             CarUserService.UserCallback callback = invocation.getArgument(0);
@@ -210,12 +215,12 @@
         // This prevents one test failure in tearDown from triggering assertion failure for single
         // CarLocalServices service.
         CarLocalServices.removeAllServices();
-        mCarImpl = new ICarImpl(context, mMockedVehicleHal, mFakeSystemInterface,
+        mCarImpl = new ICarImpl(mMockedCarTestContext, mMockedVehicleHal, mFakeSystemInterface,
                 /* errorNotifier= */ null , "MockedCar", mCarUserService);
 
         spyOnInitMockedHal();
         initMockedHal(mCarImpl, false /* no need to release */);
-        mCar = new Car(context, mCarImpl, null /* handler */);
+        mCar = new Car(mMockedCarTestContext, mCarImpl, null /* handler */);
     }
 
     @After
@@ -243,10 +248,6 @@
         return (VmsClientManager) mCarImpl.getCarInternalService(ICarImpl.INTERNAL_VMS_MANAGER);
     }
 
-    protected Context getCarServiceContext() {
-        return getContext();
-    }
-
     protected synchronized void reinitializeMockedHal() throws Exception {
         initMockedHal(mCarImpl, true /* release */);
     }
@@ -404,6 +405,29 @@
         }
     }
 
+    /**
+     * Special version of {@link ContextWrapper} that overrides {@method getResources} by returning
+     * a {@link MockResources}, so tests are free to set resources. This class represents an
+     * alternative of using Mockito spy (see b/148240178).
+     *
+     * Tests may specialize this class. If they decide so, then they are required to override
+     * {@method newMockedCarContext} to provide their own context.
+     */
+    protected static class MockedCarTestContext extends ContextWrapper {
+
+        private final Resources mMockedResources;
+
+        MockedCarTestContext(Context base) {
+            super(base);
+            mMockedResources = new MockResources(base.getResources());
+        }
+
+        @Override
+        public Resources getResources() {
+            return mMockedResources;
+        }
+    }
+
     static final class MockResources extends Resources {
         private final HashMap<Integer, Boolean> mBooleanOverrides = new HashMap<>();
         private final HashMap<Integer, Integer> mIntegerOverrides = new HashMap<>();