Merge "KV] Don't set current token if no data was moved"
diff --git a/api/current.txt b/api/current.txt
index 28863b8..72c71c6 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -43682,6 +43682,7 @@
     method public int getNetworkType();
     method public int getPhoneCount();
     method public int getPhoneType();
+    method public int getPreferredOpportunisticDataSubscription();
     method public android.telephony.ServiceState getServiceState();
     method public android.telephony.SignalStrength getSignalStrength();
     method public int getSimCarrierId();
@@ -43731,6 +43732,7 @@
     method public boolean setNetworkSelectionModeManual(java.lang.String, boolean);
     method public boolean setOperatorBrandOverride(java.lang.String);
     method public boolean setPreferredNetworkTypeToGlobal();
+    method public boolean setPreferredOpportunisticDataSubscription(int);
     method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings);
     method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
     method public deprecated void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index a3cd8a3..0114ff4 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -72,6 +72,7 @@
         "src/external/StatsPuller.cpp",
         "src/external/StatsCompanionServicePuller.cpp",
         "src/external/SubsystemSleepStatePuller.cpp",
+        "src/external/PowerStatsPuller.cpp",
         "src/external/ResourceHealthManagerPuller.cpp",
         "src/external/ResourceThermalManagerPuller.cpp",
         "src/external/StatsPullerManager.cpp",
@@ -134,6 +135,7 @@
         "android.hardware.health@2.0",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
+        "android.hardware.power.stats@1.0",
         "android.hardware.thermal@1.0",
         "libpackagelistparser",
         "libsysutils",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 5620184..21e7203 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -190,6 +190,7 @@
         ProcessCpuTime process_cpu_time = 10035;
         NativeProcessMemoryState native_process_memory_state = 10036;
         CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
+        OnDevicePowerMeasurement on_device_power_measurement = 10038;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -2262,6 +2263,27 @@
 }
 
 /**
+ * Pulls on-device power measurement information.
+ * Data defined by hardware/interfaces/power/stats/1.0/types.hal.
+ * Pulled from:
+ *   frameworks/base/cmds/statsd/src/external/PowerStatsPuller.cpp
+ */
+message OnDevicePowerMeasurement {
+    // Name of the subsystem (to which the rail belongs).
+    optional string subsystem_name = 1;
+
+    // Rail name. The rail lies within the subsystem.
+    optional string rail_name = 2;
+
+    // Time (in ms since boot) at which the rail energy value was measured.
+    // This may differ slightly from the time that statsd logs this information.
+    optional uint64 measurement_timestamp_millis = 3;
+
+    // Accumulated energy used via the rail since device boot in uWs.
+    optional uint64 energy_microwatt_secs = 4;
+}
+
+/**
  * Pulls Cpu time per frequency.
  * Pulls the time the cpu spend on the frequency index. Frequency index
  * starts from highest to lowest. The value should be monotonically
diff --git a/cmds/statsd/src/external/PowerStatsPuller.cpp b/cmds/statsd/src/external/PowerStatsPuller.cpp
new file mode 100644
index 0000000..71e5fa0
--- /dev/null
+++ b/cmds/statsd/src/external/PowerStatsPuller.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG false  // STOPSHIP if true
+#include "Log.h"
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+
+#include <vector>
+
+#include "PowerStatsPuller.h"
+#include "stats_log_util.h"
+
+using android::hardware::hidl_vec;
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using std::make_shared;
+using std::shared_ptr;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHal = nullptr;
+std::mutex gPowerStatsHalMutex;
+bool gPowerStatsExist = true; // Initialized to ensure making a first attempt.
+std::vector<RailInfo> gRailInfo;
+
+bool getPowerStatsHal() {
+    if (gPowerStatsHal == nullptr && gPowerStatsExist) {
+        gPowerStatsHal = android::hardware::power::stats::V1_0::IPowerStats::getService();
+        if (gPowerStatsHal == nullptr) {
+            ALOGW("Couldn't load power.stats HAL service");
+            gPowerStatsExist = false;
+        }
+    }
+    return gPowerStatsHal != nullptr;
+}
+
+PowerStatsPuller::PowerStatsPuller() : StatsPuller(android::util::ON_DEVICE_POWER_MEASUREMENT) {
+}
+
+bool PowerStatsPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+    std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+    if (!getPowerStatsHal()) {
+        ALOGE("power.stats Hal not loaded");
+        return false;
+    }
+
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
+
+    data->clear();
+
+    // Pull getRailInfo if necessary
+    if (gRailInfo.empty()) {
+        bool resultSuccess = true;
+        Return<void> ret = gPowerStatsHal->getRailInfo(
+                [&resultSuccess](const hidl_vec<RailInfo> &list, Status status) {
+                    resultSuccess = (status == Status::SUCCESS || status == Status::NOT_SUPPORTED);
+                    if (status != Status::SUCCESS) return;
+
+                    gRailInfo.reserve(list.size());
+                    for (size_t i = 0; i < list.size(); ++i) {
+                        gRailInfo.push_back(list[i]);
+                    }
+                });
+        if (!resultSuccess || !ret.isOk()) {
+            ALOGE("power.stats getRailInfo() failed. Description: %s", ret.description().c_str());
+            gPowerStatsHal = nullptr;
+            return false;
+        }
+        // If SUCCESS but empty, or if NOT_SUPPORTED, then never try again.
+        if (gRailInfo.empty()) {
+            ALOGE("power.stats has no rail information");
+            gPowerStatsExist = false; // No rail info, so never try again.
+            return false;
+        }
+    }
+
+    // Pull getEnergyData and write the data out
+    const hidl_vec<uint32_t> desiredRailIndices; // Empty vector indicates we want all.
+    bool resultSuccess = true;
+    Return<void> ret = gPowerStatsHal->getEnergyData(desiredRailIndices,
+                [&data, wallClockTimestampNs, elapsedTimestampNs, &resultSuccess]
+                (hidl_vec<EnergyData> energyDataList, Status status) {
+                    resultSuccess = (status == Status::SUCCESS);
+                    if (!resultSuccess) return;
+
+                    for (size_t i = 0; i < energyDataList.size(); i++) {
+                        const EnergyData& energyData = energyDataList[i];
+
+                        if (energyData.index >= gRailInfo.size()) {
+                            ALOGE("power.stats getEnergyData() returned an invalid rail index %u.",
+                                    energyData.index);
+                            resultSuccess = false;
+                            return;
+                        }
+                        const RailInfo& rail = gRailInfo[energyData.index];
+
+                        auto ptr = make_shared<LogEvent>(android::util::ON_DEVICE_POWER_MEASUREMENT,
+                              wallClockTimestampNs, elapsedTimestampNs);
+                        ptr->write(rail.subsysName);
+                        ptr->write(rail.railName);
+                        ptr->write(energyData.timestamp);
+                        ptr->write(energyData.energy);
+                        ptr->init();
+                        data->push_back(ptr);
+
+                        VLOG("power.stat: %s.%s: %llu, %llu",
+                             rail.subsysName.c_str(),
+                             rail.railName.c_str(),
+                             (unsigned long long)energyData.timestamp,
+                             (unsigned long long)energyData.energy);
+                    }
+                });
+    if (!resultSuccess || !ret.isOk()) {
+        ALOGE("power.stats getEnergyData() failed. Description: %s", ret.description().c_str());
+        gPowerStatsHal = nullptr;
+        return false;
+    }
+    return true;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/PowerStatsPuller.h b/cmds/statsd/src/external/PowerStatsPuller.h
new file mode 100644
index 0000000..dd5ff8f
--- /dev/null
+++ b/cmds/statsd/src/external/PowerStatsPuller.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Reads hal for power.stats
+ */
+class PowerStatsPuller : public StatsPuller {
+public:
+    PowerStatsPuller();
+    bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 9633980..8378ae1 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -26,6 +26,7 @@
 #include "../logd/LogEvent.h"
 #include "../stats_log_util.h"
 #include "../statscompanion_util.h"
+#include "PowerStatsPuller.h"
 #include "ResourceHealthManagerPuller.h"
 #include "ResourceThermalManagerPuller.h"
 #include "StatsCompanionServicePuller.h"
@@ -86,6 +87,9 @@
         // subsystem_sleep_state
         {android::util::SUBSYSTEM_SLEEP_STATE,
          {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
+        // on_device_power_measurement
+        {android::util::ON_DEVICE_POWER_MEASUREMENT,
+         {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
         // cpu_time_per_freq
         {android::util::CPU_TIME_PER_FREQ,
          {{3},
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0d33bbd..3d16eb8 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -572,6 +572,10 @@
      * Good practice is to first create the surface with the {@link #HIDDEN} flag
      * specified, open a transaction, set the surface layer, layer stack, alpha,
      * and position, call {@link #show} if appropriate, and close the transaction.
+     * <p>
+     * Bounds of the surface is determined by its crop and its buffer size. If the
+     * surface has no buffer or crop, the surface is boundless and only constrained
+     * by the size of its parent bounds.
      *
      * @param session The surface session, must not be null.
      * @param name The surface name, must not be null.
@@ -959,6 +963,14 @@
         }
     }
 
+    /**
+     * Bounds the surface and its children to the bounds specified. Size of the surface will be
+     * ignored and only the crop and buffer size will be used to determine the bounds of the
+     * surface. If no crop is specified and the surface has no buffer, the surface bounds is only
+     * constrained by the size of its parent bounds.
+     *
+     * @param crop Bounds of the crop to apply.
+     */
     public void setWindowCrop(Rect crop) {
         checkNotReleased();
         synchronized (SurfaceControl.class) {
@@ -966,6 +978,19 @@
         }
     }
 
+    /**
+     * Same as {@link SurfaceControl#setWindowCrop(Rect)} but sets the crop rect top left at 0, 0.
+     *
+     * @param width width of crop rect
+     * @param height height of crop rect
+     */
+    public void setWindowCrop(int width, int height) {
+        checkNotReleased();
+        synchronized (SurfaceControl.class) {
+            sGlobalTransaction.setWindowCrop(this, width, height);
+        }
+    }
+
     public void setLayerStack(int layerStack) {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -1477,6 +1502,12 @@
             return this;
         }
 
+        public Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
+            sc.checkNotReleased();
+            nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, width, height);
+            return this;
+        }
+
         @UnsupportedAppUsage
         public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
             sc.checkNotReleased();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 67f9399..2b68ec0 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -598,6 +598,7 @@
                         }
                         if (sizeChanged && !creating) {
                             mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
+                            mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
                         }
                     } finally {
                         SurfaceControl.closeTransaction();
@@ -1169,6 +1170,12 @@
         }
 
         @Override
+        public void setWindowCrop(int width, int height) {
+            super.setWindowCrop(width, height);
+            mBackgroundControl.setWindowCrop(width, height);
+        }
+
+        @Override
         public void setLayerStack(int layerStack) {
             super.setLayerStack(layerStack);
             mBackgroundControl.setLayerStack(layerStack);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0f88722..46c6fa4 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -93,6 +93,9 @@
 @UiThread
 public class ResolverActivity extends Activity {
 
+    // Temporary flag for new chooser delegate behavior.
+    boolean mEnableChooserDelegate = false;
+
     protected ResolveListAdapter mAdapter;
     private boolean mSafeForwardingMode;
     private AbsListView mAdapterView;
@@ -1216,7 +1219,13 @@
 
         @Override
         public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
-            return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
+
+            if (mEnableChooserDelegate) {
+                return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
+            } else {
+                activity.startActivityAsCaller(mResolvedIntent, options, null, false, userId);
+                return true;
+            }
         }
 
         @Override
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 9b8f120..604537f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -142,7 +142,7 @@
 
     // Used to show the dialog when BiometricService starts authentication
     void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation);
+            boolean requireConfirmation, int userId);
     // Used to hide the dialog when a biometric is authenticated
     void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 90f2002..9a7094a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -92,7 +92,7 @@
 
     // Used to show the dialog when BiometricService starts authentication
     void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation);
+            boolean requireConfirmation, int userId);
     // Used to hide the dialog when a biometric is authenticated
     void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 7fc41ac..a494e49 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -51,7 +51,7 @@
     LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
                         "drawRenderNode called on a context with no surface!");
 
-    SkSurface* backBuffer = mVkManager.getBackbufferSurface(mVkSurface);
+    SkSurface* backBuffer = mVkManager.getBackbufferSurface(&mVkSurface);
     if (backBuffer == nullptr) {
         SkDebugf("failed to get backbuffer");
         return Frame(-1, -1, 0);
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index f96b1f8..d84ec85 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,6 +16,8 @@
 
 #include "VulkanManager.h"
 
+#include <gui/Surface.h>
+
 #include "Properties.h"
 #include "RenderThread.h"
 #include "renderstate/RenderState.h"
@@ -452,7 +454,20 @@
     return backbuffer;
 }
 
-SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
+SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
+    // Recreate VulkanSurface, if ANativeWindow has been resized.
+    VulkanSurface* surface = *surfaceOut;
+    int windowWidth = 0, windowHeight = 0;
+    ANativeWindow* window = surface->mNativeWindow;
+    window->query(window, NATIVE_WINDOW_WIDTH, &windowWidth);
+    window->query(window, NATIVE_WINDOW_HEIGHT, &windowHeight);
+    if (windowWidth != surface->mWindowWidth || windowHeight != surface->mWindowHeight) {
+        ColorMode colorMode = surface->mColorMode;
+        destroySurface(surface);
+        *surfaceOut = createSurface(window, colorMode);
+        surface = *surfaceOut;
+    }
+
     VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
     SkASSERT(backbuffer);
 
@@ -717,6 +732,8 @@
         extent.height = caps.minImageExtent.height;
     }
     SkASSERT(extent.height <= caps.maxImageExtent.height);
+    surface->mWindowWidth = extent.width;
+    surface->mWindowHeight = extent.height;
 
     uint32_t imageCount = caps.minImageCount + 2;
     if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
@@ -814,7 +831,7 @@
         return nullptr;
     }
 
-    VulkanSurface* surface = new VulkanSurface(colorMode);
+    VulkanSurface* surface = new VulkanSurface(colorMode, window);
 
     VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
     memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 6702649..8594a1b 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -38,7 +38,8 @@
 
 class VulkanSurface {
 public:
-    VulkanSurface(ColorMode colorMode) : mColorMode(colorMode) {}
+    VulkanSurface(ColorMode colorMode, ANativeWindow* window)
+            : mColorMode(colorMode), mNativeWindow(window) {}
 
     sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
 
@@ -75,6 +76,9 @@
     ImageInfo* mImageInfos;
     uint16_t mCurrentTime = 0;
     ColorMode mColorMode;
+    ANativeWindow* mNativeWindow;
+    int mWindowWidth = 0;
+    int mWindowHeight = 0;
 };
 
 // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -109,7 +113,7 @@
     // Returns an SkSurface which wraps the next image returned from vkAcquireNextImageKHR. It also
     // will transition the VkImage from a present layout to color attachment so that it can be used
     // by the client for drawing.
-    SkSurface* getBackbufferSurface(VulkanSurface* surface);
+    SkSurface* getBackbufferSurface(VulkanSurface** surface);
 
     // Presents the current VkImage.
     void swapBuffers(VulkanSurface* surface);
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 3534636..4ac0188 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -56,15 +56,20 @@
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.UUID;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * @hide
@@ -94,17 +99,11 @@
 
     private final Object mSrcLock = new Object();
     //--- guarded by |mSrcLock| start
-    private long mSrcIdGenerator = 0;
-    private DataSourceDesc mCurrentDSD;
-    private long mCurrentSrcId = mSrcIdGenerator++;
-    private List<DataSourceDesc> mNextDSDs;
-    private long mNextSrcId = mSrcIdGenerator++;
-    private int mNextSourceState = NEXT_SOURCE_STATE_INIT;
-    private boolean mNextSourcePlayPending = false;
+    private SourceInfo mCurrentSourceInfo;
+    private final Queue<SourceInfo> mNextSourceInfos = new ConcurrentLinkedQueue<>();
     //--- guarded by |mSrcLock| end
+    private final AtomicLong mSrcIdGenerator = new AtomicLong(0);
 
-    private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0);
-    private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0);
     private volatile float mVolume = 1.0f;
     private VideoSize mVideoSize = new VideoSize(0, 0);
 
@@ -227,7 +226,15 @@
     @Override
     public long getBufferedPosition() {
         // Use cached buffered percent for now.
-        return getDuration() * mBufferedPercentageCurrent.get() / 100;
+        int bufferedPercentage;
+        synchronized (mSrcLock) {
+            if (mCurrentSourceInfo == null) {
+                bufferedPercentage = 0;
+            } else {
+                bufferedPercentage = mCurrentSourceInfo.mBufferedPercentage.get();
+            }
+        }
+        return getDuration() * bufferedPercentage / 100;
     }
 
     @Override
@@ -268,9 +275,8 @@
                 }
 
                 synchronized (mSrcLock) {
-                    mCurrentDSD = dsd;
-                    mCurrentSrcId = mSrcIdGenerator++;
-                    handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
+                    mCurrentSourceInfo = new SourceInfo(dsd);
+                    handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId);
                 }
             }
         });
@@ -283,10 +289,8 @@
             void process() {
                 checkArgument(dsd != null, "the DataSourceDesc cannot be null");
                 synchronized (mSrcLock) {
-                    mNextDSDs = new ArrayList<DataSourceDesc>(1);
-                    mNextDSDs.add(dsd);
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mNextSourceInfos.clear();
+                    mNextSourceInfos.add(new SourceInfo(dsd));
                 }
                 prepareNextDataSource();
             }
@@ -309,9 +313,10 @@
                 }
 
                 synchronized (mSrcLock) {
-                    mNextDSDs = new ArrayList(dsds);
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mNextSourceInfos.clear();
+                    for (DataSourceDesc dsd : dsds) {
+                        mNextSourceInfos.add(new SourceInfo(dsd));
+                    }
                 }
                 prepareNextDataSource();
             }
@@ -323,22 +328,15 @@
         return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
             @Override
             void process() {
-                synchronized (mSrcLock) {
-                    if (mNextDSDs != null) {
-                        mNextDSDs.clear();
-                        mNextDSDs = null;
-                    }
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                }
+                mNextSourceInfos.clear();
             }
         });
     }
 
     @Override
-    public @NonNull DataSourceDesc getCurrentDataSource() {
+    public DataSourceDesc getCurrentDataSource() {
         synchronized (mSrcLock) {
-            return mCurrentDSD;
+            return mCurrentSourceInfo == null ? null : mCurrentSourceInfo.mDSD;
         }
     }
 
@@ -707,34 +705,29 @@
         }
 
         boolean hasNextDSD;
-        synchronized (mSrcLock) {
-            hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty());
-        }
-
         int state = getState();
-        if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
-            // Current source has not been prepared yet.
-            return hasNextDSD;
-        }
-
         synchronized (mSrcLock) {
-            if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
+            hasNextDSD = !mNextSourceInfos.isEmpty();
+            if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
+                // Current source has not been prepared yet.
+                return hasNextDSD;
+            }
+
+            SourceInfo nextSource = mNextSourceInfos.peek();
+            if (!hasNextDSD || nextSource.mStateAsNextSource != NEXT_SOURCE_STATE_INIT) {
                 // There is no next source or it's in preparing or prepared state.
                 return hasNextDSD;
             }
 
             try {
-                mNextSourceState = NEXT_SOURCE_STATE_PREPARING;
-                handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId);
+                nextSource.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARING;
+                handleDataSource(false /* isCurrent */, nextSource.mDSD, nextSource.mId);
             } catch (Exception e) {
                 Message msg = mTaskHandler.obtainMessage(
                         MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null);
-                mTaskHandler.handleMessage(msg, mNextSrcId);
+                mTaskHandler.handleMessage(msg, nextSource.mId);
 
-                mNextDSDs.remove(0);
-                // make a new SrcId to obsolete notification for previous one.
-                mNextSrcId = mSrcIdGenerator++;
-                mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                mNextSourceInfos.poll();
                 return prepareNextDataSource();
             }
         }
@@ -749,19 +742,14 @@
 
         boolean hasNextDSD = false;
         synchronized (mSrcLock) {
-            if (mNextDSDs != null && !mNextDSDs.isEmpty()) {
+            if (!mNextSourceInfos.isEmpty()) {
                 hasNextDSD = true;
-                if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
+                SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+                if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_PREPARED) {
                     // Switch to next source only when it has been prepared.
-                    mCurrentDSD = mNextDSDs.get(0);
-                    mCurrentSrcId = mNextSrcId;
-                    mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
-                    mNextDSDs.remove(0);
-                    mNextSrcId = mSrcIdGenerator++;  // make it different from |mCurrentSrcId|
-                    mBufferedPercentageNext.set(0);
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    mCurrentSourceInfo = mNextSourceInfos.poll();
 
-                    long srcId = mCurrentSrcId;
+                    long srcId = mCurrentSourceInfo.mId;
                     try {
                         nativePlayNextDataSource(srcId);
                     } catch (Exception e) {
@@ -776,9 +764,8 @@
 
                         // Now a new current src is playing.
                         // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source.
-                        mNextSourcePlayPending = false;
                     }
-                } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
+                } else if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_INIT) {
                     hasNextDSD = prepareNextDataSource();
                 }
             }
@@ -1073,12 +1060,8 @@
             mDrmEventCallbackRecords.clear();
         }
         synchronized (mSrcLock) {
-            if (mNextDSDs != null) {
-                mNextDSDs.clear();
-                mNextDSDs = null;
-            }
-            mNextSrcId = mSrcIdGenerator++;
-            mNextSourceState = NEXT_SOURCE_STATE_INIT;
+            mCurrentSourceInfo = null;
+            mNextSourceInfos.clear();
         }
 
         synchronized (mTaskLock) {
@@ -1532,20 +1515,11 @@
             final int what = msg.arg1;
             final int extra = msg.arg2;
 
-            final DataSourceDesc dsd;
-            boolean isCurrentSrcId = false;
-            boolean isNextSrcId = false;
-            synchronized (mSrcLock) {
-                if (srcId == mCurrentSrcId) {
-                    dsd = mCurrentDSD;
-                    isCurrentSrcId = true;
-                } else if (mNextDSDs != null && !mNextDSDs.isEmpty() && srcId == mNextSrcId) {
-                    dsd = mNextDSDs.get(0);
-                    isNextSrcId = true;
-                } else {
-                    return;
-                }
+            final SourceInfo sourceInfo = getSourceInfoById(srcId);
+            if (sourceInfo == null) {
+                return;
             }
+            final DataSourceDesc dsd = sourceInfo.mDSD;
 
             switch(msg.what) {
                 case MEDIA_PREPARED:
@@ -1561,14 +1535,16 @@
                     }
 
                     synchronized (mSrcLock) {
+                        SourceInfo nextSourceInfo = mNextSourceInfos.peek();
                         Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
-                                + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
+                                + ", curSrc=" + mCurrentSourceInfo
+                                + ", nextSrc=" + nextSourceInfo);
 
-                        if (isCurrentSrcId) {
+                        if (isCurrentSource(srcId)) {
                             prepareNextDataSource();
-                        } else if (isNextSrcId) {
-                            mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
-                            if (mNextSourcePlayPending) {
+                        } else if (isNextSource(srcId)) {
+                            nextSourceInfo.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARED;
+                            if (nextSourceInfo.mPlayPendingAsNextSource) {
                                 playNextDataSource();
                             }
                         }
@@ -1621,7 +1597,7 @@
 
                 case MEDIA_PLAYBACK_COMPLETE:
                 {
-                    if (isCurrentSrcId) {
+                    if (isCurrentSource(srcId)) {
                         sendEvent(new EventNotifier() {
                             @Override
                             public void notify(EventCallback callback) {
@@ -1632,11 +1608,13 @@
                         stayAwake(false);
 
                         synchronized (mSrcLock) {
-                            mNextSourcePlayPending = true;
-
+                            SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+                            if (nextSourceInfo != null) {
+                                nextSourceInfo.mPlayPendingAsNextSource = true;
+                            }
                             Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
-                                    + ", currentSrcId=" + mCurrentSrcId
-                                    + ", nextSrcId=" + mNextSrcId);
+                                    + ", curSrc=" + mCurrentSourceInfo
+                                    + ", nextSrc=" + nextSourceInfo);
                         }
 
                         playNextDataSource();
@@ -1667,13 +1645,11 @@
                         }
                     });
 
-                    synchronized (mSrcLock) {
-                        if (isCurrentSrcId) {
-                            mBufferedPercentageCurrent.set(percent);
-                        } else if (isNextSrcId) {
-                            mBufferedPercentageNext.set(percent);
-                        }
+                    SourceInfo src = getSourceInfoById(srcId);
+                    if (src != null) {
+                        src.mBufferedPercentage.set(percent);
                     }
+
                     return;
                 }
 
@@ -1751,7 +1727,7 @@
                     });
 
                     if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
-                        if (isCurrentSrcId) {
+                        if (isCurrentSource(srcId)) {
                             prepareNextDataSource();
                         }
                     }
@@ -1854,6 +1830,7 @@
                 }
             }
         }
+
     }
 
     /*
@@ -2130,7 +2107,7 @@
                         @Override
                         public void notify(DrmEventCallback callback) {
                             callback.onDrmPrepared(
-                                    MediaPlayer2Impl.this, mCurrentDSD, prepareDrmStatus);
+                                    MediaPlayer2Impl.this, getCurrentDataSource(), prepareDrmStatus);
                         }
                     });
 
@@ -2196,7 +2173,7 @@
 
         // call the callback outside the lock
         if (mOnDrmConfigHelper != null)  {
-            mOnDrmConfigHelper.onDrmConfig(this, mCurrentDSD);
+            mOnDrmConfigHelper.onDrmConfig(this, getCurrentDataSource());
         }
 
         synchronized (mDrmLock) {
@@ -2817,7 +2794,7 @@
                 @Override
                 public void notify(DrmEventCallback callback) {
                     callback.onDrmPrepared(
-                            mediaPlayer, mCurrentDSD, status);
+                            mediaPlayer, getCurrentDataSource(), status);
                 }
             });
 
@@ -3084,9 +3061,7 @@
             } catch (Exception e) {
                 status = CALL_STATUS_ERROR_UNKNOWN;
             }
-            synchronized (mSrcLock) {
-                mDSD = mCurrentDSD;
-            }
+            mDSD = getCurrentDataSource();
 
             if (mMediaCallType != CALL_COMPLETED_SEEK_TO) {
                 synchronized (mTaskLock) {
@@ -3129,4 +3104,50 @@
             super(detailMessage);
         }
     };
+
+    private final class SourceInfo {
+        final DataSourceDesc mDSD;
+        final long mId = mSrcIdGenerator.getAndIncrement();
+        AtomicInteger mBufferedPercentage = new AtomicInteger(0);
+
+        // m*AsNextSource (below) only applies to pending data sources in the playlist;
+        // the meanings of mCurrentSourceInfo.{mStateAsNextSource,mPlayPendingAsNextSource}
+        // are undefined.
+        int mStateAsNextSource = NEXT_SOURCE_STATE_INIT;
+        boolean mPlayPendingAsNextSource = false;
+
+        SourceInfo(DataSourceDesc dsd) {
+            this.mDSD = dsd;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s(%d)", SourceInfo.class.getName(), mId);
+        }
+
+    }
+
+    private SourceInfo getSourceInfoById(long srcId) {
+        synchronized (mSrcLock) {
+            if (isCurrentSource(srcId)) {
+                return mCurrentSourceInfo;
+            }
+            if (isNextSource(srcId)) {
+                return mNextSourceInfos.peek();
+            }
+        }
+        return null;
+    }
+
+    private boolean isCurrentSource(long srcId) {
+        synchronized (mSrcLock) {
+            return mCurrentSourceInfo != null && mCurrentSourceInfo.mId == srcId;
+        }
+    }
+
+    private boolean isNextSource(long srcId) {
+        SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+        return nextSourceInfo != null && nextSourceInfo.mId == srcId;
+    }
+
 }
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 70f9bb6..2823149 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -39,8 +39,8 @@
     <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP Suite-B security -->
     <string name="wifi_security_short_eap_suiteb" translatable="false">Suite-B</string>
 
-    <!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. -->
-    <string name="wifi_security_none" translatable="false">None</string>
+    <!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. [CHAR LIMIT=40] -->
+    <string name="wifi_security_none">None</string>
 
     <!-- Do not translate.  Terminology for wifi with WEP security -->
     <string name="wifi_security_wep" translatable="false">WEP</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
index 1aeb075..e824508 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
@@ -44,7 +44,14 @@
 
     @Override
     public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
-        action(context, category, "", taggedData);
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+        if (taggedData != null) {
+            for (Pair<Integer, Object> pair : taggedData) {
+                logMaker.addTaggedData(pair.first, pair.second);
+            }
+        }
+        MetricsLogger.action(logMaker);
     }
 
     @Override
@@ -58,19 +65,12 @@
     }
 
     @Override
-    public void action(Context context, int category, String pkg,
-            Pair<Integer, Object>... taggedData) {
-        if (taggedData == null || taggedData.length == 0) {
-            MetricsLogger.action(context, category, pkg);
-        } else {
-            final LogMaker logMaker = new LogMaker(category)
-                    .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
-                    .setPackageName(pkg);
-            for (Pair<Integer, Object> pair : taggedData) {
-                logMaker.addTaggedData(pair.first, pair.second);
-            }
-            MetricsLogger.action(logMaker);
-        }
+    public void action(Context context, int category, String pkg) {
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
+                .setPackageName(pkg);
+
+        MetricsLogger.action(logMaker);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
index b60364e..f187688 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
@@ -51,7 +51,7 @@
     /**
      * Logs an user action.
      */
-    void action(Context context, int category, String pkg, Pair<Integer, Object>... taggedData);
+    void action(Context context, int category, String pkg);
 
     /**
      * Generically log action.
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index 188204e..8cc3b5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -79,7 +79,10 @@
         }
     }
 
-    public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
+    /**
+     * Logs a simple action without page id or attribution
+     */
+    public void action(Context context, int category,  Pair<Integer, Object>... taggedData) {
         for (LogWriter writer : mLoggerWriters) {
             writer.action(context, category, taggedData);
         }
@@ -88,10 +91,9 @@
     /**
      * Logs a generic Settings event.
      */
-    public void action(Context context, int category, String pkg,
-            Pair<Integer, Object>... taggedData) {
+    public void action(Context context, int category, String pkg) {
         for (LogWriter writer : mLoggerWriters) {
-            writer.action(context, category, pkg, taggedData);
+            writer.action(context, category, pkg);
         }
     }
 
@@ -135,16 +137,22 @@
                 // Not loggable
                 return;
             }
-            action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, action,
-                    Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+            action(sourceMetricsCategory,
+                    MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                    SettingsEnums.PAGE_UNKNOWN,
+                    action,
+                    0);
             return;
         } else if (TextUtils.equals(cn.getPackageName(), context.getPackageName())) {
             // Going to a Setting internal page, skip click logging in favor of page's own
             // visibility logging.
             return;
         }
-        action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, cn.flattenToString(),
-                Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+        action(sourceMetricsCategory,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                cn.flattenToString(),
+                0);
     }
 
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
index 71f3789..320380f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
@@ -15,6 +15,7 @@
 package com.android.settingslib.core.instrumentation;
 
 import android.annotation.Nullable;
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -22,12 +23,9 @@
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentSkipListSet;
@@ -117,10 +115,9 @@
             return;
         }
 
-        final Pair<Integer, Object> valueData;
+        final int intVal;
         if (value instanceof Long) {
             final Long longVal = (Long) value;
-            final int intVal;
             if (longVal > Integer.MAX_VALUE) {
                 intVal = Integer.MAX_VALUE;
             } else if (longVal < Integer.MIN_VALUE) {
@@ -128,47 +125,45 @@
             } else {
                 intVal = longVal.intValue();
             }
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    intVal);
         } else if (value instanceof Integer) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    value);
+            intVal = (int) value;
         } else if (value instanceof Boolean) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    (Boolean) value ? 1 : 0);
+            intVal = (Boolean) value ? 1 : 0;
         } else if (value instanceof Float) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
-                    value);
-        } else if (value instanceof String) {
-            Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
-            valueData = null;
+            final float floatValue = (float) value;
+            if (floatValue > Integer.MAX_VALUE) {
+                intVal = Integer.MAX_VALUE;
+            } else if (floatValue < Integer.MIN_VALUE) {
+                intVal = Integer.MIN_VALUE;
+            } else {
+                intVal = (int) floatValue;
+            }
         } else {
             Log.w(LOG_TAG, "Tried to log unloggable object" + value);
-            valueData = null;
+            return;
         }
-        if (valueData != null) {
-            // Pref key exists in set, log it's change in metrics.
-            mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
-                    Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
-                    valueData);
-        }
+        // Pref key exists in set, log it's change in metrics.
+        mMetricsFeature.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                prefKey,
+                intVal);
     }
 
     @VisibleForTesting
     void logPackageName(String key, String value) {
         final String prefKey = mTag + "/" + key;
-        mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE, value,
-                Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey));
+        mMetricsFeature.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                prefKey + ":" + value,
+                0);
     }
 
     private void safeLogValue(String key, String value) {
         new AsyncPackageCheck().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, key, value);
     }
 
-    public static String buildCountName(String prefKey, Object value) {
-        return prefKey + "|" + value;
-    }
-
     public static String buildPrefKey(String tag, String key) {
         return tag + "/" + key;
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
index 603f838..4ec6fb2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -17,8 +17,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
@@ -27,7 +25,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.util.Pair;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
@@ -77,10 +74,11 @@
         mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
 
         verify(mLogWriter).action(
-                eq(mContext),
-                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
-                anyString(),
-                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+                MetricsEvent.SETTINGS_GESTURES,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                Intent.ACTION_ASSIST,
+                0);
     }
 
     @Test
@@ -90,10 +88,11 @@
         mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
 
         verify(mLogWriter).action(
-                eq(mContext),
-                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
-                anyString(),
-                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+                MetricsEvent.SETTINGS_GESTURES,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                "pkg/cls",
+                0);
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
index be671e6..6285fcd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -15,25 +15,16 @@
  */
 package com.android.settingslib.core.instrumentation;
 
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .ACTION_SETTINGS_PREFERENCE_CHANGE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE;
 
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.util.Pair;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
@@ -41,7 +32,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -50,11 +40,11 @@
 
     private static final String TEST_TAG = "tag";
     private static final String TEST_KEY = "key";
+    private static final String TEST_TAGGED_KEY = TEST_TAG + "/" + TEST_KEY;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
 
-    private ArgumentMatcher<Pair<Integer, Object>> mNamePairMatcher;
     @Mock
     private MetricsFeatureProvider mMetricsFeature;
     private SharedPreferencesLogger mSharedPrefLogger;
@@ -63,7 +53,6 @@
     public void init() {
         MockitoAnnotations.initMocks(this);
         mSharedPrefLogger = new SharedPreferencesLogger(mContext, TEST_TAG, mMetricsFeature);
-        mNamePairMatcher = pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, String.class);
     }
 
     @Test
@@ -77,9 +66,11 @@
         editor.putInt(TEST_KEY, 2);
         editor.putInt(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+        verify(mMetricsFeature, times(6)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
@@ -92,12 +83,16 @@
         editor.putBoolean(TEST_KEY, false);
 
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, true)));
-        verify(mMetricsFeature, times(3)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, false)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                1);
+        verify(mMetricsFeature, times(3)).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                0);
     }
 
     @Test
@@ -109,9 +104,11 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+        verify(mMetricsFeature, times(4)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
@@ -121,10 +118,11 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, veryBigNumber);
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(
-                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MAX_VALUE)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                Integer.MAX_VALUE);
     }
 
     @Test
@@ -134,10 +132,10 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, veryNegativeNumber);
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(
-                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MIN_VALUE)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY, Integer.MIN_VALUE);
     }
 
     @Test
@@ -149,38 +147,20 @@
         editor.putFloat(TEST_KEY, 1);
         editor.putFloat(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE, Float.class)));
+        verify(mMetricsFeature, times(4)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
     public void logPackage_shouldUseLogPackageApi() {
         mSharedPrefLogger.logPackageName("key", "com.android.settings");
-        verify(mMetricsFeature).action(any(Context.class),
-                eq(ACTION_SETTINGS_PREFERENCE_CHANGE),
-                eq("com.android.settings"),
-                any(Pair.class));
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, Class clazz) {
-        return pair -> pair.first == tag && isInstanceOfType(pair.second, clazz);
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) {
-        return pair -> pair.first == tag
-                && isInstanceOfType(pair.second, Integer.class)
-                && pair.second.equals((bool ? 1 : 0));
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) {
-        return pair -> pair.first == tag
-                && isInstanceOfType(pair.second, Integer.class)
-                && pair.second.equals(val);
-    }
-
-    /** Returns true if the instance is assignable to the type Clazz. */
-    private static boolean isInstanceOfType(Object instance, Class<?> clazz) {
-        return clazz.isInstance(instance);
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                "tag/key:com.android.settings",
+                0);
     }
 }
diff --git a/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
new file mode 100644
index 0000000..311f30bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index 67c0adf..5ca34b0 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -14,157 +14,169 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="bottom"
-    android:background="@color/biometric_dialog_dim_color"
-    android:orientation="vertical">
+    android:layout_height="match_parent">
 
-    <!-- This is not a Space since Spaces cannot be clicked -->
-    <View
-        android:id="@+id/space"
+    <ImageView
+        android:id="@+id/background"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1" />
+        android:layout_height="match_parent"
+        android:scaleType="center" />
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
+        android:layout_height="match_parent"
+        android:gravity="bottom"
+        android:background="@color/biometric_dialog_dim_color"
+        android:orientation="vertical">
 
-        <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-         on horizontal/portrait orientation -->
+        <!-- This is not a Space since Spaces cannot be clicked -->
         <View
-            android:id="@+id/left_space"
-            android:layout_weight="1"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"/>
+            android:id="@+id/space"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
 
         <LinearLayout
-            android:id="@+id/dialog"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:background="@drawable/biometric_dialog_bg"
-            android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
-            android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
-            android:layout_marginRight="@dimen/biometric_dialog_border_padding">
+            android:orientation="horizontal">
 
-            <TextView
-                android:id="@+id/title"
-                android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:layout_marginTop="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:textSize="20sp"
-                android:maxLines="1"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:marqueeRepeatLimit="marquee_forever"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <TextView
-                android:id="@+id/subtitle"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="8dp"
-                android:layout_marginStart="24dp"
-                android:layout_marginEnd="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:textSize="16sp"
-                android:maxLines="1"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:marqueeRepeatLimit="marquee_forever"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <TextView
-                android:id="@+id/description"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:paddingTop="8dp"
-                android:textSize="16sp"
-                android:maxLines="4"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <ImageView
-                android:id="@+id/biometric_icon"
-                android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
-                android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginTop="48dp"
-                android:scaleType="fitXY" />
-
-            <TextView
-                android:id="@+id/error"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:paddingTop="16dp"
-                android:paddingBottom="24dp"
-                android:textSize="12sp"
-                android:gravity="center_horizontal"
-                android:accessibilityLiveRegion="polite"
-                android:contentDescription="@string/accessibility_biometric_dialog_help_area"
-                android:textColor="?android:attr/textColorSecondary"/>
+            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+             on horizontal/portrait orientation -->
+            <View
+                android:id="@+id/left_space"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"/>
 
             <LinearLayout
+                android:id="@+id/dialog"
                 android:layout_width="match_parent"
-                android:layout_height="72dip"
-                android:paddingTop="24dp"
-                android:layout_gravity="center_vertical"
-                style="?android:attr/buttonBarStyle"
-                android:orientation="horizontal"
-                android:measureWithLargestChild="true">
-                <Space android:id="@+id/leftSpacer"
-                    android:layout_width="12dp"
-                    android:layout_height="match_parent"
-                    android:visibility="visible" />
-                <!-- Negative Button -->
-                <Button android:id="@+id/button2"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
-                    android:gravity="center"
-                    android:maxLines="2" />
-                <Space android:id="@+id/middleSpacer"
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:visibility="visible" />
-                <!-- Positive Button -->
-                <Button android:id="@+id/button1"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    style="@*android:style/Widget.DeviceDefault.Button.Colored"
-                    android:gravity="center"
-                    android:maxLines="2"
-                    android:text="@string/biometric_dialog_confirm"
-                    android:visibility="gone"/>
-                <Space android:id="@+id/rightSpacer"
-                    android:layout_width="12dip"
-                    android:layout_height="match_parent"
-                    android:visibility="visible" />
-            </LinearLayout>
-        </LinearLayout>
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:background="@drawable/biometric_dialog_bg"
+                android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
+                android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
+                android:layout_marginRight="@dimen/biometric_dialog_border_padding">
 
-        <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-         on horizontal/portrait orientation -->
-        <View
-            android:id="@+id/right_space"
-            android:layout_weight="1"
-            android:layout_width="0dp"
-            android:layout_height="match_parent" />
+                <TextView
+                    android:id="@+id/title"
+                    android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:layout_marginTop="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:textSize="20sp"
+                    android:maxLines="1"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:marqueeRepeatLimit="marquee_forever"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <TextView
+                    android:id="@+id/subtitle"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dp"
+                    android:layout_marginStart="24dp"
+                    android:layout_marginEnd="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:textSize="16sp"
+                    android:maxLines="1"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:marqueeRepeatLimit="marquee_forever"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <TextView
+                    android:id="@+id/description"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:paddingTop="8dp"
+                    android:textSize="16sp"
+                    android:maxLines="4"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <ImageView
+                    android:id="@+id/biometric_icon"
+                    android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
+                    android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
+                    android:layout_gravity="center_horizontal"
+                    android:layout_marginTop="48dp"
+                    android:scaleType="fitXY" />
+
+                <TextView
+                    android:id="@+id/error"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:paddingTop="16dp"
+                    android:paddingBottom="24dp"
+                    android:textSize="12sp"
+                    android:gravity="center_horizontal"
+                    android:accessibilityLiveRegion="polite"
+                    android:contentDescription="@string/accessibility_biometric_dialog_help_area"
+                    android:textColor="?android:attr/textColorSecondary"/>
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="72dip"
+                    android:paddingTop="24dp"
+                    android:layout_gravity="center_vertical"
+                    style="?android:attr/buttonBarStyle"
+                    android:orientation="horizontal"
+                    android:measureWithLargestChild="true">
+                    <Space android:id="@+id/leftSpacer"
+                        android:layout_width="12dp"
+                        android:layout_height="match_parent"
+                        android:visibility="visible" />
+                    <!-- Negative Button -->
+                    <Button android:id="@+id/button2"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+                        android:gravity="center"
+                        android:maxLines="2" />
+                    <Space android:id="@+id/middleSpacer"
+                        android:layout_width="0dp"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:visibility="visible" />
+                    <!-- Positive Button -->
+                    <Button android:id="@+id/button1"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        style="@*android:style/Widget.DeviceDefault.Button.Colored"
+                        android:gravity="center"
+                        android:maxLines="2"
+                        android:text="@string/biometric_dialog_confirm"
+                        android:visibility="gone"/>
+                    <Space android:id="@+id/rightSpacer"
+                        android:layout_width="12dip"
+                        android:layout_height="match_parent"
+                        android:visibility="visible" />
+                </LinearLayout>
+            </LinearLayout>
+
+            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+             on horizontal/portrait orientation -->
+            <View
+                android:id="@+id/right_space"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="match_parent" />
+
+        </LinearLayout>
 
     </LinearLayout>
 
-</LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar_window.xml b/packages/SystemUI/res/layout/navigation_bar_window.xml
index 6fa46d4..f98cbd8 100644
--- a/packages/SystemUI/res/layout/navigation_bar_window.xml
+++ b/packages/SystemUI/res/layout/navigation_bar_window.xml
@@ -20,6 +20,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/navigation_bar_frame"
+    android:theme="@style/Theme.SystemUI"
     android:layout_height="match_parent"
     android:layout_width="match_parent">
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index fbcf068..5e6d272 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -296,7 +296,7 @@
                 new WakefulnessLifecycle());
 
         mProviders.put(FragmentService.class, () ->
-                new FragmentService(mContext));
+                new FragmentService());
 
         mProviders.put(ExtensionController.class, () ->
                 new ExtensionControllerImpl(mContext));
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 67bc8b6..c0047c0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -140,7 +140,7 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         if (DEBUG) Log.d(TAG, "showBiometricDialog, type: " + type);
         // Remove these messages as they are part of the previous client
         mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
@@ -151,6 +151,7 @@
         args.arg2 = receiver;
         args.argi1 = type;
         args.arg3 = requireConfirmation;
+        args.argi2 = userId;
         mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
     }
 
@@ -194,7 +195,8 @@
         }
         mReceiver = (IBiometricPromptReceiver) args.arg2;
         mCurrentDialog.setBundle((Bundle)args.arg1);
-        mCurrentDialog.setRequireConfirmation((boolean)args.arg3);
+        mCurrentDialog.setRequireConfirmation((boolean) args.arg3);
+        mCurrentDialog.setUserId(args.argi2);
         mCurrentDialog.setSkipIntro(skipAnimation);
         mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
         mDialogShowing = true;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 1faae9d..38427ad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -16,15 +16,19 @@
 
 package com.android.systemui.biometrics;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
 import android.hardware.biometrics.BiometricPrompt;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -64,6 +68,8 @@
     private final IBinder mWindowToken = new Binder();
     private final Interpolator mLinearOutSlowIn;
     private final WindowManager mWindowManager;
+    private final UserManager mUserManager;
+    private final DevicePolicyManager mDevicePolicyManager;
     private final float mAnimationTranslationOffset;
     private final int mErrorColor;
     private final int mTextColor;
@@ -79,6 +85,7 @@
     private boolean mWasForceRemoved;
     private boolean mSkipIntro;
     protected boolean mRequireConfirmation;
+    private int mUserId; // used to determine if we should show work background
 
     protected abstract void updateIcon(int lastState, int newState);
     protected abstract int getHintStringResourceId();
@@ -121,7 +128,9 @@
         super(context);
         mCallback = callback;
         mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = mContext.getSystemService(WindowManager.class);
+        mUserManager = mContext.getSystemService(UserManager.class);
+        mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
         mAnimationTranslationOffset = getResources()
                 .getDimension(R.dimen.biometric_dialog_animation_translation_offset);
 
@@ -199,6 +208,18 @@
         final TextView description = mLayout.findViewById(R.id.description);
         final Button negative = mLayout.findViewById(R.id.button2);
         final Button positive = mLayout.findViewById(R.id.button1);
+        final ImageView backgroundView = mLayout.findViewById(R.id.background);
+
+        if (mUserManager.isManagedProfile(mUserId)) {
+            final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
+                    mContext.getTheme());
+            image.setColorFilter(mDevicePolicyManager.getOrganizationColorForUser(mUserId),
+                    PorterDuff.Mode.DARKEN);
+            backgroundView.setImageDrawable(image);
+        } else {
+            backgroundView.setImageDrawable(null);
+            backgroundView.setBackgroundColor(R.color.biometric_dialog_dim_color);
+        }
 
         if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) {
             mDialog.getLayoutParams().width = (int) mDialogWidth;
@@ -329,6 +350,10 @@
         positive.setVisibility(View.VISIBLE);
     }
 
+    public void setUserId(int userId) {
+        mUserId = userId;
+    }
+
     public ViewGroup getLayout() {
         return mLayout;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 0ed1cd1..779a86c 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -59,11 +59,11 @@
     private FragmentController mFragments;
     private FragmentLifecycleCallbacks mLifecycleCallbacks;
 
-    FragmentHostManager(Context context, FragmentService manager, View rootView) {
-        mContext = context;
+    FragmentHostManager(FragmentService manager, View rootView) {
+        mContext = rootView.getContext();
         mManager = manager;
         mRootView = rootView;
-        mConfigChanges.applyNewConfig(context.getResources());
+        mConfigChanges.applyNewConfig(mContext.getResources());
         createFragmentHost(null);
     }
 
@@ -203,6 +203,10 @@
         }
     }
 
+    public static void removeAndDestroy(View view) {
+        Dependency.get(FragmentService.class).removeAndDestroy(view);
+    }
+
     class HostCallbacks extends FragmentHostCallback<FragmentHostManager> {
         public HostCallbacks() {
             super(mContext, FragmentHostManager.this.mHandler, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index f9bf4f5..bf7d629 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -14,18 +14,13 @@
 
 package com.android.systemui.fragments;
 
-import android.content.Context;
 import android.content.res.Configuration;
-import android.os.Bundle;
 import android.os.Handler;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.view.View;
 
 import com.android.systemui.ConfigurationChangedReceiver;
 import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIApplication;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -40,11 +35,6 @@
 
     private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
     private final Handler mHandler = new Handler();
-    private final Context mContext;
-
-    public FragmentService(Context context) {
-        mContext = context;
-    }
 
     public FragmentHostManager getFragmentHostManager(View view) {
         View root = view.getRootView();
@@ -56,6 +46,13 @@
         return state.getFragmentHostManager();
     }
 
+    public void removeAndDestroy(View view) {
+        final FragmentHostState state = mHosts.remove(view.getRootView());
+        if (state != null) {
+            state.mFragmentHostManager.destroy();
+        }
+    }
+
     public void destroyAll() {
         for (FragmentHostState state : mHosts.values()) {
             state.mFragmentHostManager.destroy();
@@ -84,7 +81,7 @@
 
         public FragmentHostState(View view) {
             mView = view;
-            mFragmentHostManager = new FragmentHostManager(mContext, FragmentService.this, mView);
+            mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView);
         }
 
         public void sendConfigurationChange(Configuration newConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index daaefb9..0c8f487 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -27,9 +27,9 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
-import android.util.Pair;
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.IStatusBar;
@@ -164,7 +164,7 @@
         default void onRotationProposal(int rotation, boolean isValid) { }
 
         default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver,
-                int type, boolean requireConfirmation) { }
+                int type, boolean requireConfirmation, int userId) { }
         default void onBiometricAuthenticated() { }
         default void onBiometricHelp(String message) { }
         default void onBiometricError(String error) { }
@@ -524,13 +524,14 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = bundle;
             args.arg2 = receiver;
             args.argi1 = type;
             args.arg3 = requireConfirmation;
+            args.argi2 = userId;
             mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
                     .sendToTarget();
         }
@@ -774,8 +775,9 @@
                         mCallbacks.get(i).showBiometricDialog(
                                 (Bundle) someArgs.arg1,
                                 (IBiometricPromptReceiver) someArgs.arg2,
-                                someArgs.argi1,
-                                (boolean) someArgs.arg3);
+                                someArgs.argi1 /* type */,
+                                (boolean) someArgs.arg3 /* requireConfirmation */,
+                                someArgs.argi2 /* userId */);
                     }
                     someArgs.recycle();
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index 65476fd..eaf52cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -298,7 +298,8 @@
     public interface StateListener {
 
         /**
-         * Callback before the new state is applied, for those who need to preempt the change
+         * Callback before the new state is applied, for those who need to preempt the change.
+         *
          * @param oldState state before the change
          * @param newState new state to be applied in {@link #onStateChanged}
          */
@@ -314,21 +315,26 @@
         /**
          * Required callback. Get the new state and do what you will with it. Keep in mind that
          * other listeners are typically unordered and don't rely on your work being done before
-         * other peers
+         * other peers.
          *
-         * Only called if the state is actually different
+         * Only called if the state is actually different.
+         *
          * @param newState the new {@link StatusBarState}
          */
         public void onStateChanged(int newState);
 
         /**
          * Callback to be notified when Dozing changes. Dozing is stored separately from state.
+         *
          * @param isDozing {@code true} if dozing according to {@link StatusBar}
          */
         public default void onDozingChanged(boolean isDozing) {}
 
         /**
          * Callback to be notified when the doze amount changes. Useful for animations.
+         * Note: this will be called for each animation frame. Please be careful to avoid
+         * performance regressions.
+         *
          * @param linear A number from 0 to 1, where 1 means that the device is dozing.
          * @param eased Same as {@code linear} but transformed by an interpolator.
          */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index b0ac6ec..b29889d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.util.MathUtils;
 import android.util.TimeUtils;
 
 import com.android.systemui.Dependency;
@@ -29,6 +30,7 @@
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.io.FileDescriptor;
@@ -37,7 +39,8 @@
 /**
  * Class to control all aspects about light bar changes.
  */
-public class LightBarTransitionsController implements Dumpable, Callbacks {
+public class LightBarTransitionsController implements Dumpable, Callbacks,
+        StatusBarStateController.StateListener {
 
     public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
     private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
@@ -45,6 +48,7 @@
     private final Handler mHandler;
     private final DarkIntensityApplier mApplier;
     private final KeyguardMonitor mKeyguardMonitor;
+    private final StatusBarStateController mStatusBarStateController;
 
     private boolean mTransitionDeferring;
     private long mTransitionDeferringStartTime;
@@ -55,6 +59,7 @@
     private ValueAnimator mTintAnimator;
     private float mDarkIntensity;
     private float mNextDarkIntensity;
+    private float mDozeAmount;
     private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
         @Override
         public void run() {
@@ -66,13 +71,17 @@
         mApplier = applier;
         mHandler = new Handler();
         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
         SysUiServiceProvider.getComponent(context, CommandQueue.class)
                 .addCallbacks(this);
+        mStatusBarStateController.addListener(this);
+        mDozeAmount = mStatusBarStateController.getDozeAmount();
     }
 
     public void destroy(Context context) {
         SysUiServiceProvider.getComponent(context, CommandQueue.class)
                 .removeCallbacks(this);
+        mStatusBarStateController.removeListener(this);
     }
 
     public void saveState(Bundle outState) {
@@ -173,7 +182,11 @@
 
     private void setIconTintInternal(float darkIntensity) {
         mDarkIntensity = darkIntensity;
-        mApplier.applyDarkIntensity(darkIntensity);
+        dispatchDark();
+    }
+
+    private void dispatchDark() {
+        mApplier.applyDarkIntensity(MathUtils.lerp(mDarkIntensity, 0f, mDozeAmount));
     }
 
     @Override
@@ -196,6 +209,15 @@
         pw.print(" mNextDarkIntensity="); pw.println(mNextDarkIntensity);
     }
 
+    @Override
+    public void onStateChanged(int newState) { }
+
+    @Override
+    public void onDozeAmountChanged(float linear, float eased) {
+        mDozeAmount = eased;
+        dispatchDark();
+    }
+
     /**
      * Interface to apply a specific dark intensity.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 4406b14..0cf1b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -144,6 +144,7 @@
 
     private OverviewProxyService mOverviewProxyService;
 
+    private boolean mIsOnDefaultDisplay = true;
     public boolean mHomeBlockedThisTouch;
 
     private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
@@ -241,6 +242,11 @@
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         mNavigationBarView = (NavigationBarView) view;
+        final Display display = view.getDisplay();
+        // It may not have display when running unit test.
+        if (display != null) {
+            mIsOnDefaultDisplay = display.getDisplayId() == Display.DEFAULT_DISPLAY;
+        }
 
         mNavigationBarView.setComponents(mStatusBar.getPanel());
         mNavigationBarView.setDisabledFlags(mDisabledFlags1);
@@ -253,8 +259,6 @@
         prepareNavigationBarView();
         checkNavBarModes();
 
-        setDisabled2Flags(mDisabledFlags2);
-
         IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
         filter.addAction(Intent.ACTION_SCREEN_ON);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -262,16 +266,23 @@
         notifyNavigationBarScreenOn();
         mOverviewProxyService.addCallback(mOverviewProxyListener);
 
-        RotationContextButton rotationButton = mNavigationBarView.getRotateSuggestionButton();
-        rotationButton.setListener(mRotationButtonListener);
-        rotationButton.addRotationCallback(mRotationWatcher);
+        // Currently there is no accelerometer sensor on non-default display.
+        if (mIsOnDefaultDisplay) {
+            final RotationContextButton rotationButton =
+                    mNavigationBarView.getRotateSuggestionButton();
+            rotationButton.setListener(mRotationButtonListener);
+            rotationButton.addRotationCallback(mRotationWatcher);
 
-        // Reset user rotation pref to match that of the WindowManager if starting in locked mode
-        // This will automatically happen when switching from auto-rotate to locked mode
-        if (rotationButton.isRotationLocked()) {
-            final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
-            rotationButton.setRotationLockedAtAngle(winRotation);
+            // Reset user rotation pref to match that of the WindowManager if starting in locked
+            // mode. This will automatically happen when switching from auto-rotate to locked mode.
+            if (display != null && rotationButton.isRotationLocked()) {
+                final int winRotation = display.getRotation();
+                rotationButton.setRotationLockedAtAngle(winRotation);
+            }
+        } else {
+            mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
         }
+        setDisabled2Flags(mDisabledFlags2);
     }
 
     @Override
@@ -389,7 +400,7 @@
 
     @Override
     public void onRotationProposal(final int rotation, boolean isValid) {
-        final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
+        final int winRotation = mNavigationBarView.getDisplay().getRotation();
         final boolean rotateSuggestionsDisabled = RotationContextButton
                 .hasDisable2RotateSuggestionFlag(mDisabledFlags2);
         if (RotationContextButton.DEBUG_ROTATION) {
@@ -477,10 +488,13 @@
             updateScreenPinningGestures();
         }
 
-        final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
-        if (masked2 != mDisabledFlags2) {
-            mDisabledFlags2 = masked2;
-            setDisabled2Flags(masked2);
+        // Only default display supports rotation suggestions.
+        if (mIsOnDefaultDisplay) {
+            final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
+            if (masked2 != mDisabledFlags2) {
+                mDisabledFlags2 = masked2;
+                setDisabled2Flags(masked2);
+            }
         }
     }
 
@@ -881,13 +895,23 @@
         if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
         if (navigationBarView == null) return null;
 
+        final NavigationBarFragment fragment = new NavigationBarFragment();
+        navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View v) {
+                final FragmentHostManager fragmentHost = FragmentHostManager.get(v);
+                fragmentHost.getFragmentManager().beginTransaction()
+                        .replace(R.id.navigation_bar_frame, fragment, TAG)
+                        .commit();
+                fragmentHost.addTagListener(TAG, listener);
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View v) {
+                FragmentHostManager.removeAndDestroy(v);
+            }
+        });
         context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
-        FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
-        NavigationBarFragment fragment = new NavigationBarFragment();
-        fragmentHost.getFragmentManager().beginTransaction()
-                .replace(R.id.navigation_bar_frame, fragment, TAG)
-                .commit();
-        fragmentHost.addTagListener(TAG, listener);
         return navigationBarView;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 2c3c27f..b43bbdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -264,8 +264,7 @@
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mDisplay = ((WindowManager) context.getSystemService(
-                Context.WINDOW_SERVICE)).getDefaultDisplay();
+        mDisplay = context.getDisplay();
 
         mVertical = false;
         mLongClickableAccessibilityButton = false;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
new file mode 100644
index 0000000..0031c32
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class LightBarTransitionsControllerTest extends SysuiTestCase {
+
+    @Mock
+    private DarkIntensityApplier mApplier;
+    private LightBarTransitionsController mLightBarTransitionsController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+        mLightBarTransitionsController = new LightBarTransitionsController(mContext, mApplier);
+    }
+
+    @Test
+    public void setIconsDark_lightAndDark() {
+        mLightBarTransitionsController.setIconsDark(true /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(1f));
+
+        mLightBarTransitionsController.setIconsDark(false /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(0f));
+    }
+
+    @Test
+    public void onDozeAmountChanged_lightWhenDozing() {
+        mLightBarTransitionsController.onDozeAmountChanged(1f /* linear */, 1f /* eased */);
+        mLightBarTransitionsController.setIconsDark(true /* dark */, false /* animate */);
+        verify(mApplier, times(2)).applyDarkIntensity(eq(0f));
+
+        reset(mApplier);
+        mLightBarTransitionsController.setIconsDark(false /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(0f));
+    }
+
+}
diff --git a/services/Android.bp b/services/Android.bp
index bea51be..3390438 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -23,6 +23,7 @@
         "services.companion",
         "services.coverage",
         "services.devicepolicy",
+        "services.intelligence",
         "services.midi",
         "services.net",
         "services.print",
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0bae1f3..d1392d0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19170,6 +19170,9 @@
             if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
                 return false;
             }
+            if (uid == SHELL_UID || uid == ROOT_UID) {
+                return false;
+            }
             synchronized (mPidsSelfLocked) {
                 final ProcessRecord pr = mPidsSelfLocked.get(pid);
                 return pr == null || pr.mountMode != Zygote.MOUNT_EXTERNAL_FULL;
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 61836fdd..2c2d404 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -358,7 +358,7 @@
             if (mBundle != null) {
                 try {
                     mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver,
-                            getBiometricType(), mRequireConfirmation);
+                            getBiometricType(), mRequireConfirmation, getTargetUserId());
                 } catch (RemoteException e) {
                     Slog.e(getLogTag(), "Unable to show biometric dialog", e);
                 }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index bc3cc3b..7aa2e47 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -485,7 +485,7 @@
                 BiometricAuthenticator.Identifier biometric, int userId)
                 throws RemoteException {
             if (mFaceServiceReceiver != null) {
-                if (biometric instanceof Face) {
+                if (biometric == null || biometric instanceof Face) {
                     mFaceServiceReceiver.onAuthenticationSucceeded(deviceId, (Face)biometric);
                 } else {
                     Slog.e(TAG, "onAuthenticationSucceeded received non-face biometric");
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b404c41..1c7572e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3610,7 +3610,7 @@
                         NotificationRecord r = mNotificationsByKey.get(adjustment.getKey());
                         if (r != null && mAssistants.isSameUser(token, r.getUserId())) {
                             applyAdjustment(r, adjustment);
-                            r.applyAdjustments();
+                            r.applyImportanceFromAdjustments();
                             if (r.getImportance() == IMPORTANCE_NONE) {
                                 cancelNotificationsFromListener(token, new String[]{r.getKey()});
                             } else {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 84d0c01..a11b03f 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -664,6 +664,18 @@
                             .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_REPLIES,
                                     getSmartReplies().size()));
                 }
+            }
+            applyImportanceFromAdjustments();
+        }
+    }
+
+    /**
+     * Update importance from the adjustment.
+     */
+    public void applyImportanceFromAdjustments() {
+        synchronized (mAdjustments) {
+            for (Adjustment adjustment : mAdjustments) {
+                Bundle signals = adjustment.getSignals();
                 if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) {
                     int importance = signals.getInt(Adjustment.KEY_IMPORTANCE);
                     importance = Math.max(IMPORTANCE_UNSPECIFIED, importance);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 26f6e96..ea190a7 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1126,101 +1126,108 @@
             throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
         }
 
-        if (!params.isMultiPackage) {
-            Preconditions.checkNotNull(mPackageName);
-            Preconditions.checkNotNull(mSigningDetails);
-            Preconditions.checkNotNull(mResolvedBaseFile);
+        final IPackageInstallObserver2 localObserver;
+        if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+            localObserver = null;
+        } else {
+            if (!params.isMultiPackage) {
+                Preconditions.checkNotNull(mPackageName);
+                Preconditions.checkNotNull(mSigningDetails);
+                Preconditions.checkNotNull(mResolvedBaseFile);
 
-            if (needToAskForPermissionsLocked()) {
-                // User needs to confirm installation;
-                // give installer an intent they can use to involve
-                // user.
-                final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
-                intent.setPackage(mPm.getPackageInstallerPackageName());
-                intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
-                try {
-                    mRemoteObserver.onUserActionRequired(intent);
-                } catch (RemoteException ignored) {
-                }
-
-                // Commit was keeping session marked as active until now; release
-                // that extra refcount so session appears idle.
-                closeInternal(false);
-                return null;
-            }
-
-            // Inherit any packages and native libraries from existing install that
-            // haven't been overridden.
-            if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
-                try {
-                    final List<File> fromFiles = mResolvedInheritedFiles;
-                    final File toDir = resolveStageDirLocked();
-
-                    if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
-                    if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
-                        throw new IllegalStateException("mInheritedFilesBase == null");
+                if (needToAskForPermissionsLocked()) {
+                    // User needs to confirm installation;
+                    // give installer an intent they can use to involve
+                    // user.
+                    final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
+                    intent.setPackage(mPm.getPackageInstallerPackageName());
+                    intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+                    try {
+                        mRemoteObserver.onUserActionRequired(intent);
+                    } catch (RemoteException ignored) {
                     }
 
-                    if (isLinkPossible(fromFiles, toDir)) {
-                        if (!mResolvedInstructionSets.isEmpty()) {
-                            final File oatDir = new File(toDir, "oat");
-                            createOatDirs(mResolvedInstructionSets, oatDir);
+                    // Commit was keeping session marked as active until now; release
+                    // that extra refcount so session appears idle.
+                    closeInternal(false);
+                    return null;
+                }
+
+                // Inherit any packages and native libraries from existing install that
+                // haven't been overridden.
+                if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+                    try {
+                        final List<File> fromFiles = mResolvedInheritedFiles;
+                        final File toDir = resolveStageDirLocked();
+
+                        if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
+                        if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
+                            throw new IllegalStateException("mInheritedFilesBase == null");
                         }
-                        // pre-create lib dirs for linking if necessary
-                        if (!mResolvedNativeLibPaths.isEmpty()) {
-                            for (String libPath : mResolvedNativeLibPaths) {
-                                // "/lib/arm64" -> ["lib", "arm64"]
-                                final int splitIndex = libPath.lastIndexOf('/');
-                                if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
-                                    Slog.e(TAG,
-                                            "Skipping native library creation for linking due to "
-                                                    + "invalid path: " + libPath);
-                                    continue;
-                                }
-                                final String libDirPath = libPath.substring(1, splitIndex);
-                                final File libDir = new File(toDir, libDirPath);
-                                if (!libDir.exists()) {
-                                    NativeLibraryHelper.createNativeLibrarySubdir(libDir);
-                                }
-                                final String archDirPath = libPath.substring(splitIndex + 1);
-                                NativeLibraryHelper.createNativeLibrarySubdir(
-                                        new File(libDir, archDirPath));
+
+                        if (isLinkPossible(fromFiles, toDir)) {
+                            if (!mResolvedInstructionSets.isEmpty()) {
+                                final File oatDir = new File(toDir, "oat");
+                                createOatDirs(mResolvedInstructionSets, oatDir);
                             }
+                            // pre-create lib dirs for linking if necessary
+                            if (!mResolvedNativeLibPaths.isEmpty()) {
+                                for (String libPath : mResolvedNativeLibPaths) {
+                                    // "/lib/arm64" -> ["lib", "arm64"]
+                                    final int splitIndex = libPath.lastIndexOf('/');
+                                    if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
+                                        Slog.e(TAG,
+                                                "Skipping native library creation for linking due"
+                                                        + " to invalid path: " + libPath);
+                                        continue;
+                                    }
+                                    final String libDirPath = libPath.substring(1, splitIndex);
+                                    final File libDir = new File(toDir, libDirPath);
+                                    if (!libDir.exists()) {
+                                        NativeLibraryHelper.createNativeLibrarySubdir(libDir);
+                                    }
+                                    final String archDirPath = libPath.substring(splitIndex + 1);
+                                    NativeLibraryHelper.createNativeLibrarySubdir(
+                                            new File(libDir, archDirPath));
+                                }
+                            }
+                            linkFiles(fromFiles, toDir, mInheritedFilesBase);
+                        } else {
+                            // TODO: this should delegate to DCS so the system process
+                            // avoids holding open FDs into containers.
+                            copyFiles(fromFiles, toDir);
                         }
-                        linkFiles(fromFiles, toDir, mInheritedFilesBase);
-                    } else {
-                        // TODO: this should delegate to DCS so the system process
-                        // avoids holding open FDs into containers.
-                        copyFiles(fromFiles, toDir);
+                    } catch (IOException e) {
+                        throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+                                "Failed to inherit existing install", e);
                     }
-                } catch (IOException e) {
-                    throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
-                            "Failed to inherit existing install", e);
                 }
+
+                // TODO: surface more granular state from dexopt
+                mInternalProgress = 0.5f;
+                computeProgressLocked(true);
+
+                // Unpack native libraries
+                extractNativeLibraries(mResolvedStageDir, params.abiOverride,
+                        mayInheritNativeLibs());
             }
 
-            // TODO: surface more granular state from dexopt
-            mInternalProgress = 0.5f;
-            computeProgressLocked(true);
+            // We've reached point of no return; call into PMS to install the stage.
+            // Regardless of success or failure we always destroy session.
+            localObserver = new IPackageInstallObserver2.Stub() {
+                @Override
+                public void onUserActionRequired(Intent intent) {
+                    throw new IllegalStateException();
+                }
 
-            // Unpack native libraries
-            extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
+                @Override
+                public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+                        Bundle extras) {
+                    destroyInternal();
+                    dispatchSessionFinished(returnCode, msg, extras);
+                }
+            };
         }
-        // We've reached point of no return; call into PMS to install the stage.
-        // Regardless of success or failure we always destroy session.
-        final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
-            @Override
-            public void onUserActionRequired(Intent intent) {
-                throw new IllegalStateException();
-            }
-
-            @Override
-            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
-                    Bundle extras) {
-                destroyInternal();
-                dispatchSessionFinished(returnCode, msg, extras);
-            }
-        };
 
         final UserHandle user;
         if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
@@ -1230,11 +1237,9 @@
         }
 
         mRelinquished = true;
-        final PackageManagerService.ActiveInstallSession activeInstallSession =
-                new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
-                        localObserver, params, mInstallerPackageName, mInstallerUid, user,
-                        mSigningDetails);
-        return activeInstallSession;
+        return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
+                localObserver, params, mInstallerPackageName, mInstallerUid, user,
+                mSigningDetails);
     }
 
     private static void maybeRenameFile(File from, File to) throws PackageManagerException {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 72d3406..8a0c416 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9308,7 +9308,7 @@
         }
     }
 
-    private SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
+    private @Nullable SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
         LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             return null;
@@ -9580,16 +9580,26 @@
     private void applyDefiningSharedLibraryUpdateLocked(
             PackageParser.Package pkg, SharedLibraryInfo libInfo,
             BiConsumer<SharedLibraryInfo, SharedLibraryInfo> action) {
+        // Note that libraries defined by this package may be null if:
+        // - Package manager was unable to create the shared library. The package still
+        //   gets installed, but the shared library does not get created.
+        // Or:
+        // - Package manager is in a state where package isn't scanned yet. This will
+        //   get called again after scanning to fix the dependencies.
         if (pkg.isLibrary()) {
             if (pkg.staticSharedLibName != null) {
                 SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
                         pkg.staticSharedLibName, pkg.staticSharedLibVersion);
-                action.accept(definedLibrary, libInfo);
+                if (definedLibrary != null) {
+                    action.accept(definedLibrary, libInfo);
+                }
             } else {
                 for (String libraryName : pkg.libraryNames) {
                     SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
                             libraryName, SharedLibraryInfo.VERSION_UNDEFINED);
-                    action.accept(definedLibrary, libInfo);
+                    if (definedLibrary != null) {
+                        action.accept(definedLibrary, libInfo);
+                    }
                 }
             }
         }
@@ -17763,30 +17773,58 @@
         return true;
     }
 
+    private static class DeletePackageAction {
+        public final PackageSetting deletingPs;
+
+        private DeletePackageAction(PackageSetting deletingPs) {
+            this.deletingPs = deletingPs;
+        }
+    }
+
+    /**
+     * @return a {@link DeletePackageAction} if the provided package may be deleted, {@code null}
+     * otherwise.
+     */
+    @Nullable
+    private DeletePackageAction mayDeletePackageLIF(@NonNull String packageName) {
+        synchronized (mPackages) {
+            final PackageSetting ps;
+            ps = mSettings.mPackages.get(packageName);
+            if (ps == null) {
+                return null;
+            }
+            return new DeletePackageAction(ps);
+        }
+    }
+
     /*
      * This method handles package deletion in general
      */
-    private boolean deletePackageLIF(String packageName, UserHandle user,
+    private boolean deletePackageLIF(@NonNull String packageName, UserHandle user,
             boolean deleteCodeAndResources, int[] allUserHandles, int flags,
             PackageRemovedInfo outInfo, boolean writeSettings,
             PackageParser.Package replacingPackage) {
-        if (packageName == null) {
-            Slog.w(TAG, "Attempt to delete null packageName.");
+        final DeletePackageAction action = mayDeletePackageLIF(packageName);
+        if (null == action) {
             return false;
         }
 
         if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
 
-        PackageSetting ps;
-        synchronized (mPackages) {
-            ps = mSettings.mPackages.get(packageName);
-            if (ps == null) {
-                Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
-                return false;
-            }
+        return executeDeletePackageLIF(action, packageName, user, deleteCodeAndResources,
+                allUserHandles, flags, outInfo, writeSettings, replacingPackage);
+    }
 
-            if (ps.parentPackageName != null && (!isSystemApp(ps)
-                    || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
+    private boolean executeDeletePackageLIF(DeletePackageAction action,
+            String packageName, UserHandle user, boolean deleteCodeAndResources,
+            int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
+            boolean writeSettings, PackageParser.Package replacingPackage) {
+        final PackageSetting ps = action.deletingPs;
+        final boolean systemApp = isSystemApp(ps);
+        synchronized (mPackages) {
+
+            if (ps.parentPackageName != null
+                    && (!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
                 if (DEBUG_REMOVE) {
                     Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
                             + ((user == null) ? UserHandle.USER_ALL : user));
@@ -17794,9 +17832,7 @@
                 final int removedUserId = (user != null) ? user.getIdentifier()
                         : UserHandle.USER_ALL;
 
-                if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) {
-                    return false;
-                }
+                clearPackageStateForUserLIF(ps, removedUserId, outInfo);
                 markPackageUninstalledForUserLPw(ps, user);
                 scheduleWritePackageRestrictionsLocked(user);
                 return true;
@@ -17809,7 +17845,7 @@
         }
 
 
-        if (((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
+        if (((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
                 && user.getIdentifier() != UserHandle.USER_ALL)) {
             // The caller is asking that the package only be deleted for a single
             // user.  To do this, we just mark its uninstalled state and delete
@@ -17818,7 +17854,7 @@
             // semantics than normal for uninstalling system apps.
             markPackageUninstalledForUserLPw(ps, user);
 
-            if (!isSystemApp(ps)) {
+            if (!systemApp) {
                 // Do not uninstall the APK if an app should be cached
                 boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
                 if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
@@ -17826,9 +17862,7 @@
                     // we need to do is clear this user's data and save that
                     // it is uninstalled.
                     if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
-                    if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
-                        return false;
-                    }
+                    clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
                     scheduleWritePackageRestrictionsLocked(user);
                     return true;
                 } else {
@@ -17844,9 +17878,7 @@
                 // we need to do is clear this user's data and save that
                 // it is uninstalled.
                 if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
-                if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
-                    return false;
-                }
+                clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
                 scheduleWritePackageRestrictionsLocked(user);
                 return true;
             }
@@ -17872,8 +17904,9 @@
             }
         }
 
-        boolean ret = false;
-        if (isSystemApp(ps)) {
+        // TODO(b/109941548): break reasons for ret = false out into mayDelete method
+        final boolean ret;
+        if (systemApp) {
             if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
             // When an updated system application is deleted we delete the existing resources
             // as well and fall back to existing code in system partition
@@ -17902,7 +17935,7 @@
             // If we uninstalled an update to a system app there may be some
             // child packages that appeared as they are declared in the system
             // app but were not declared in the update.
-            if (isSystemApp(ps)) {
+            if (systemApp) {
                 synchronized (mPackages) {
                     PackageSetting updatedPs = mSettings.getPackageLPr(ps.name);
                     final int childCount = (updatedPs.childPackageNames != null)
@@ -17963,7 +17996,7 @@
         mSettings.writeKernelMappingLPr(ps);
     }
 
-    private boolean clearPackageStateForUserLIF(PackageSetting ps, int userId,
+    private void clearPackageStateForUserLIF(PackageSetting ps, int userId,
             PackageRemovedInfo outInfo) {
         final PackageParser.Package pkg;
         synchronized (mPackages) {
@@ -17999,8 +18032,6 @@
             outInfo.removedUsers = userIds;
             outInfo.broadcastUsers = userIds;
         }
-
-        return true;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index ec78560..10121c4 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -567,11 +567,11 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation);
+                mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation, userId);
             } catch (RemoteException ex) {
             }
         }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index d30cd19..3cece11 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1749,6 +1749,7 @@
                 .setName(getSurfaceControl() + " - animation-bounds")
                 .setSize(getSurfaceWidth(), getSurfaceHeight());
         final SurfaceControl boundsLayer = builder.build();
+        t.setWindowCrop(boundsLayer, getSurfaceWidth(), getSurfaceHeight());
         t.show(boundsLayer);
         return boundsLayer;
     }
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index e358ad5..9633864 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -52,7 +52,7 @@
                     .setColorLayer(true)
                     .setParent(null) // TODO: Work-around for b/69259549
                     .build();
-
+            transaction.setWindowCrop(surface, w, h);
             transaction.setLayerStack(surface, dc.getDisplayId());
             transaction.setAlpha(surface, 1);
             transaction.setLayer(surface, layer);
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 65c8e96..3accaf8 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -309,6 +309,7 @@
             // TODO: Once we use geometry from hierarchy this falls away.
             t.setSize(mDimState.mDimLayer, bounds.width(), bounds.height());
             t.setPosition(mDimState.mDimLayer, bounds.left, bounds.top);
+            t.setWindowCrop(mDimState.mDimLayer, bounds.width(), bounds.height());
             if (!mDimState.isVisible) {
                 mDimState.isVisible = true;
                 t.show(mDimState.mDimLayer);
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 4eb021c..b49d304 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -187,6 +187,7 @@
                 }
                 t.setPosition(mSurface, mSurfaceFrame.left, mSurfaceFrame.top);
                 t.setSize(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
+                t.setWindowCrop(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
                 t.show(mSurface);
             } else if (mSurface != null) {
                 t.hide(mSurface);
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 3ea615a..66063c40 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -16,12 +16,12 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_ADAPTER;
 import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_START_DELAYED;
 import static com.android.server.wm.SurfaceAnimatorProto.LEASH;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -305,6 +305,7 @@
                 .setName(surface + " - animation-leash")
                 .setSize(width, height);
         final SurfaceControl leash = builder.build();
+        t.setWindowCrop(surface, width, height);
         if (!hidden) {
             t.show(leash);
         }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 3493111..073601d 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -259,6 +259,7 @@
         final Rect stackBounds = getBounds();
         getPendingTransaction()
                 .setSize(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
+                .setWindowCrop(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
                 .setPosition(mAnimationBackgroundSurface, mTmpRect.left - stackBounds.left,
                         mTmpRect.top - stackBounds.top);
         scheduleAnimation();
@@ -789,6 +790,7 @@
             return;
         }
         transaction.setSize(mSurfaceControl, width, height);
+        transaction.setWindowCrop(mSurfaceControl, width, height);
         mLastSurfaceSize.set(width, height);
     }
 
diff --git a/services/intelligence/Android.bp b/services/intelligence/Android.bp
new file mode 100644
index 0000000..2df1235
--- /dev/null
+++ b/services/intelligence/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.intelligence",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
similarity index 100%
rename from services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java
rename to services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
diff --git a/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
similarity index 100%
rename from services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java
rename to services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
diff --git a/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
similarity index 100%
rename from services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java
rename to services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
diff --git a/services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
similarity index 100%
rename from services/autofill/java/com/android/server/intelligence/RemoteIntelligenceService.java
rename to services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index e67f8d3..9ab06a1 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -12,10 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
-##############################################################
-# FrameworksServicesLib app just for Robolectric test target #
-##############################################################
+###################################################################
+# FrameworksServicesLib app just for Robolectric test target      #
+###################################################################
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -32,81 +31,51 @@
 
 include $(BUILD_PACKAGE)
 
-##############################################
-# FrameworksServices Robolectric test target #
-##############################################
+###################################################################
+# FrameworksServicesLib Robolectric test target.                  #
+###################################################################
 include $(CLEAR_VARS)
 
-# Dependency platform-robolectric-android-all-stubs below contains a bunch of Android classes as
-# stubs that throw RuntimeExceptions when we use them. The goal is to include hidden APIs that
-# weren't included in Robolectric's Android jar files. However, we are testing the framework itself
-# here, so if we write stuff that is being used in the tests and exist in
-# platform-robolectric-android-all-stubs, the class loader is going to pick up the latter, and thus
-# we are going to test what we don't want. To solve this:
-#
-#   1. If the class being used should be visible to bundled apps:
-#      => Bypass the stubs target by including them in LOCAL_SRC_FILES and LOCAL_AIDL_INCLUDES
-#         (if aidl).
-#
-#   2. If it's not visible:
-#      => Remove the class from the stubs jar (common/robolectric/android-all/android-all-stubs.jar)
-#         and add the class path to
-#         common/robolectric/android-all/android-all-stubs_removed_classes.txt.
-#
+LOCAL_MODULE := FrameworksServicesRoboTests
 
-INTERNAL_BACKUP := ../../core/java/com/android/internal/backup
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
-    $(call all-java-files-under, ../../core/java/android/app/backup) \
-    $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
-    $(call all-java-files-under, ../../core/java/android/util/proto) \
-    ../../core/java/android/content/pm/PackageInfo.java \
-    ../../core/java/android/app/IBackupAgent.aidl \
-    ../../core/java/android/util/KeyValueSettingObserver.java \
-    ../../core/java/android/content/pm/PackageParser.java \
-    ../../core/java/android/content/pm/SigningInfo.java
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/res
 
-LOCAL_AIDL_INCLUDES := \
-    $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
-    $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
-    ../../core/java/android/app/IBackupAgent.aidl
+LOCAL_JAVA_RESOURCE_DIRS := config
 
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    platform-robolectric-android-all-stubs \
-    android-support-test \
-    guava \
-    mockito-robolectric-prebuilt \
+# Include the testing libraries
+LOCAL_JAVA_LIBRARIES := \
     platform-test-annotations \
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
     truth-prebuilt \
     testng
 
-LOCAL_JAVA_LIBRARIES := \
-    junit \
-    platform-robolectric-3.6.2-prebuilt
-
 LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib
-LOCAL_MODULE := FrameworksServicesRoboTests
 
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
-###############################################################
-# FrameworksServices runner target to run the previous target #
-###############################################################
+###################################################################
+# FrameworksServicesLib runner target to run the previous target. #
+###################################################################
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := RunFrameworksServicesRoboTests
 
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    FrameworksServicesRoboTests
+LOCAL_JAVA_LIBRARIES := \
+    FrameworksServicesRoboTests \
+    platform-test-annotations \
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
+    truth-prebuilt \
+    testng
 
 LOCAL_TEST_PACKAGE := FrameworksServicesLib
 
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))backup/java
-
-include prebuilts/misc/common/robolectric/3.6.2/run_robotests.mk
+include external/robolectric-shadows/run_robotests.mk
\ No newline at end of file
diff --git a/services/robotests/config/robolectric.properties b/services/robotests/config/robolectric.properties
new file mode 100644
index 0000000..850557a
--- /dev/null
+++ b/services/robotests/config/robolectric.properties
@@ -0,0 +1 @@
+sdk=NEWEST_SDK
\ No newline at end of file
diff --git a/services/robotests/src/android/app/backup/BackupUtilsTest.java b/services/robotests/src/android/app/backup/BackupUtilsTest.java
index 04a2a14..099cde0 100644
--- a/services/robotests/src/android/app/backup/BackupUtilsTest.java
+++ b/services/robotests/src/android/app/backup/BackupUtilsTest.java
@@ -22,14 +22,11 @@
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.annotation.internal.DoNotInstrument;
 
 import java.io.File;
@@ -38,9 +35,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"android.app.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 @DoNotInstrument
 public class BackupUtilsTest {
diff --git a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
index 0d2c221..5b226f3 100644
--- a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
@@ -25,22 +25,16 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.util.KeyValueSettingObserver;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 /** Tests for {@link BackupAgentTimeoutParameters}. */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
-@SystemLoaderClasses({KeyValueSettingObserver.class})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupAgentTimeoutParametersTest {
     private ContentResolver mContentResolver;
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
index 2a32c2e..affa1f3 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
@@ -23,21 +23,15 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.util.KeyValueSettingObserver;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
-@SystemLoaderClasses({KeyValueSettingObserver.class})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupManagerConstantsTest {
     private static final String PACKAGE_NAME = "some.package.name";
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index de915ab..c4cb593 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -22,7 +22,9 @@
 import static com.android.server.backup.testing.TransportData.localTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpTransports;
+
 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.eq;
@@ -45,24 +47,23 @@
 import android.os.PowerSaveState;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
+
 import com.android.server.backup.testing.BackupManagerServiceTestUtils;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportNotRegisteredException;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowAppBackupUtils;
 import com.android.server.testing.shadows.ShadowBinder;
 import com.android.server.testing.shadows.ShadowKeyValueBackupJob;
 import com.android.server.testing.shadows.ShadowKeyValueBackupTask;
-import java.io.File;
-import java.util.List;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implements;
@@ -71,9 +72,11 @@
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowSettings;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26, shadows = {ShadowAppBackupUtils.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.io.File;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowAppBackupUtils.class})
 @Presubmit
 public class BackupManagerServiceTest {
     private static final String TAG = "BMSTest";
diff --git a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
index dd0a58d..8e17209 100644
--- a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
+++ b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
@@ -22,19 +22,14 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class KeyValueBackupJobTest {
     private Context mContext;
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index 051a4a0..693092d 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -56,17 +56,14 @@
 import com.android.server.backup.transport.TransportClient;
 import com.android.server.backup.transport.TransportClientManager;
 import com.android.server.backup.transport.TransportNotRegisteredException;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import com.android.server.testing.shadows.FrameworkShadowContextImpl;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPackageManager;
 
 import java.util.ArrayList;
@@ -75,12 +72,7 @@
 import java.util.Set;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {FrameworkShadowContextImpl.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportManagerTest {
     private static final String PACKAGE_A = "some.package.a";
@@ -682,7 +674,7 @@
                     transport.getTransportComponent().getPackageName(),
                     ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         }
-        setUpTransports(transportSet.toArray(new TransportData[transportSet.size()]));
+        setUpTransports(transportSet.toArray(new TransportData[0]));
         TransportManager transportManager = createTransportManager(selectedTransport, transports);
         transportManager.registerTransports();
         return transportManager;
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
index 3b6e038..3f57240 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
@@ -19,17 +19,16 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.util.Arrays;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkHashTest {
     private static final int HASH_LENGTH_BYTES = 256 / 8;
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
index 383bf1d..4354db7 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
@@ -21,22 +21,20 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
+
 import com.android.internal.util.Preconditions;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.base.Charsets;
-import java.io.ByteArrayInputStream;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-// Include android.util.proto in addition to classes under test because the latest versions of
-// android.util.proto.Proto{Input|Output}Stream are not part of Robolectric.
-@SystemLoaderPackages({"com.android.server.backup", "android.util.proto"})
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkListingTest {
     private static final String CHUNK_A = "CHUNK_A";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
index 1dd7dc8..17c9a86 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
@@ -21,21 +21,18 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.base.Charsets;
-import java.io.ByteArrayInputStream;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-// Include android.util.proto in addition to classes under test because the latest versions of
-// android.util.proto.Proto{Input|Output}Stream are not part of Robolectric.
-@SystemLoaderPackages({"com.android.server.backup", "android.util.proto"})
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkTest {
     private static final String CHUNK_A = "CHUNK_A";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
index 1cd1528..0bf1417 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
@@ -19,16 +19,14 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class EncryptedChunkOrderingTest {
     private static final byte[] TEST_BYTE_ARRAY_1 = new byte[] {1, 2, 3, 4, 5};
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
index 2cc3ef8..d0e5fb3 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
@@ -17,32 +17,35 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.android.server.backup.testing.CryptoTestUtils.generateAesKey;
+
 import static com.google.common.truth.Truth.assertThat;
-import static java.nio.charset.StandardCharsets.UTF_8;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.security.SecureRandom;
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.GCMParameterSpec;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.security.SecureRandom;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkEncryptorTest {
     private static final String MAC_ALGORITHM = "HmacSHA256";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
index 11796c0..2bbbf28 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
@@ -19,20 +19,19 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkHasherTest {
     private static final String KEY_ALGORITHM = "AES";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
index c5f9b10..8e801a1 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
@@ -17,21 +17,22 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.testng.Assert.assertThrows;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.util.Arrays;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class EncryptedChunkTest {
     private static final byte[] CHUNK_HASH_1_BYTES =
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
index b162557..2f872be 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
@@ -17,25 +17,25 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
 import com.android.server.backup.encryption.chunk.ChunksMetadataProto;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
 import org.mockito.Mock;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class InlineLengthsEncryptedChunkEncoderTest {
 
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
index b61dbe9..978bddb 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
@@ -17,25 +17,25 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
 import com.android.server.backup.encryption.chunk.ChunksMetadataProto;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
 import org.mockito.Mock;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class LengthlessEncryptedChunkEncoderTest {
     private static final byte[] TEST_NONCE =
@@ -74,7 +74,7 @@
     }
 
     @Test
-    public void getChunkOrderingType_returnsExplicitStartsType() throws Exception {
+    public void getChunkOrderingType_returnsExplicitStartsType() {
         assertThat(mEncoder.getChunkOrderingType()).isEqualTo(ChunksMetadataProto.EXPLICIT_STARTS);
     }
 }
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
index 8b54e1e..19ef8fb 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
@@ -17,23 +17,23 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.testng.Assert.assertThrows;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.io.ByteArrayOutputStream;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.io.ByteArrayOutputStream;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RawBackupWriterTest {
     private static final byte[] TEST_BYTES = {1, 2, 3, 4, 5, 6};
diff --git a/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
index b771039..fd7ced2 100644
--- a/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
+++ b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
@@ -7,6 +7,7 @@
 import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.robolectric.Shadows.shadowOf;
 import static org.testng.Assert.expectThrows;
 
@@ -21,17 +22,24 @@
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
 import android.os.Build;
-import android.os.Build.VERSION_CODES;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
 import com.android.server.testing.shadows.ShadowFullBackup;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplicationPackageManager;
+import org.robolectric.shadows.ShadowEnvironment;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -41,32 +49,20 @@
 import java.nio.file.Files;
 import java.nio.file.attribute.FileTime;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplicationPackageManager;
-import org.robolectric.shadows.ShadowEnvironment;
-
-@RunWith(FrameworkRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 @Config(
-        manifest = Config.NONE,
-        sdk = 26,
         shadows = {
             ShadowBackupDataInput.class,
             ShadowBackupDataOutput.class,
             ShadowEnvironment.class,
             ShadowFullBackup.class,
         })
-@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
-@SystemLoaderClasses({PackageInfo.class, SigningInfo.class})
 public class AppMetadataBackupWriterTest {
     private static final String TEST_PACKAGE = "com.test.package";
     private static final String TEST_PACKAGE_INSTALLER = "com.test.package.installer";
     private static final Long TEST_PACKAGE_VERSION_CODE = 100L;
 
+    private PackageManager mPackageManager;
     private ShadowApplicationPackageManager mShadowPackageManager;
     private File mFilesDir;
     private File mBackupDataOutputFile;
@@ -76,8 +72,8 @@
     public void setUp() throws Exception {
         Application application = RuntimeEnvironment.application;
 
-        PackageManager packageManager = application.getPackageManager();
-        mShadowPackageManager = (ShadowApplicationPackageManager) shadowOf(packageManager);
+        mPackageManager = application.getPackageManager();
+        mShadowPackageManager = (ShadowApplicationPackageManager) shadowOf(mPackageManager);
 
         mFilesDir = RuntimeEnvironment.application.getFilesDir();
         mBackupDataOutputFile = new File(mFilesDir, "output");
@@ -87,7 +83,7 @@
                         mBackupDataOutputFile, ParcelFileDescriptor.MODE_READ_WRITE);
         FullBackupDataOutput output =
                 new FullBackupDataOutput(pfd, /* quota */ -1, /* transportFlags */ 0);
-        mBackupWriter = new AppMetadataBackupWriter(output, packageManager);
+        mBackupWriter = new AppMetadataBackupWriter(output, mPackageManager);
     }
 
     @After
@@ -211,36 +207,6 @@
      *     N* (signature byte array in ascii format per Signature.toCharsString())
      * </pre>
      */
-    @Config(sdk = VERSION_CODES.O)
-    @Test
-    public void testBackupManifest_whenApiO_writesCorrectApi() throws Exception {
-        PackageInfo packageInfo =
-                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
-        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
-
-        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
-
-        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
-        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
-        assertThat(manifest.length).isEqualTo(7);
-        assertThat(manifest[3]).isEqualTo(Integer.toString(VERSION_CODES.O)); // platform version
-        manifestFile.delete();
-    }
-
-    /**
-     * The manifest format is:
-     *
-     * <pre>
-     *     BACKUP_MANIFEST_VERSION
-     *     package name
-     *     package version code
-     *     platform version code
-     *     installer package name (can be empty)
-     *     boolean (1 if archive includes .apk, otherwise 0)
-     *     # of signatures N
-     *     N* (signature byte array in ascii format per Signature.toCharsString())
-     * </pre>
-     */
     @Test
     public void testBackupManifest_withoutInstallerPackage_writesEmptyInstaller() throws Exception {
         PackageInfo packageInfo = createPackageInfo(TEST_PACKAGE, null, TEST_PACKAGE_VERSION_CODE);
@@ -394,7 +360,7 @@
     }
 
     @Test
-    public void testBackupObb_withNoObbData_doesNotWriteBytesToOutput() throws Exception {
+    public void testBackupObb_withNoObbData_doesNotWriteBytesToOutput() {
         PackageInfo packageInfo =
                 createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
         File obbDir = createObbDirForPackage(packageInfo.packageName);
@@ -416,7 +382,7 @@
         packageInfo.setLongVersionCode(versionCode);
         mShadowPackageManager.addPackage(packageInfo);
         if (installerPackageName != null) {
-            mShadowPackageManager.setInstallerPackageName(packageName, installerPackageName);
+            mPackageManager.setInstallerPackageName(packageName, installerPackageName);
         }
         return packageInfo;
     }
diff --git a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
index 646367e..6ee6eb6 100644
--- a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
@@ -46,20 +46,18 @@
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.TransportManager;
-import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportData;
+import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportClient;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowSlog;
 
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
@@ -69,9 +67,8 @@
 import java.util.List;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26, shadows = ShadowSlog.class)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowSlog.class)
 @Presubmit
 public class PerformInitializeTaskTest {
     @Mock private BackupManagerService mBackupManagerService;
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
index 3730335..b00b922 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
@@ -20,29 +20,24 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class AgentExceptionTest {
     @Test
-    public void testTransitory_isTransitory() throws Exception {
+    public void testTransitory_isTransitory() {
         AgentException exception = AgentException.transitory();
 
         assertThat(exception.isTransitory()).isTrue();
     }
 
     @Test
-    public void testTransitory_withCause() throws Exception {
+    public void testTransitory_withCause() {
         Exception cause = new IOException();
 
         AgentException exception = AgentException.transitory(cause);
@@ -52,14 +47,14 @@
     }
 
     @Test
-    public void testPermanent_isNotTransitory() throws Exception {
+    public void testPermanent_isNotTransitory() {
         AgentException exception = AgentException.permanent();
 
         assertThat(exception.isTransitory()).isFalse();
     }
 
     @Test
-    public void testPermanent_withCause() throws Exception {
+    public void testPermanent_withCause() {
         Exception cause = new IOException();
 
         AgentException exception = AgentException.permanent(cause);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
index 5ea74f1..d5603d6 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
@@ -20,18 +20,13 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupExceptionTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
index 31e8333..a0afb5e 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
@@ -27,9 +27,6 @@
 import android.util.Log;
 
 import com.android.server.backup.BackupManagerService;
-import com.android.server.backup.remote.RemoteResult;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowEventLog;
 import com.android.server.testing.shadows.ShadowSlog;
 
@@ -37,17 +34,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLog;
 
-import java.lang.reflect.Field;
-
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {ShadowEventLog.class, ShadowSlog.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowEventLog.class, ShadowSlog.class})
 @Presubmit
 public class KeyValueBackupReporterTest {
     @Mock private BackupManagerService mBackupManagerService;
@@ -57,33 +48,31 @@
     private KeyValueBackupReporter mReporter;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         mReporter = new KeyValueBackupReporter(mBackupManagerService, mObserver, mMonitor);
     }
 
     @Test
-    public void testMoreDebug_isFalse() throws Exception {
-        boolean moreDebug = KeyValueBackupReporter.MORE_DEBUG;
-
-        assertThat(moreDebug).isFalse();
+    public void testMoreDebug_isFalse() {
+        assertThat(KeyValueBackupReporter.MORE_DEBUG).isFalse();
     }
 
     @Test
-    public void testOnNewThread_logsCorrectly() throws Exception {
+    public void testOnNewThread_logsCorrectly() {
         KeyValueBackupReporter.onNewThread("foo");
 
         assertLogcat(TAG, Log.DEBUG);
     }
 
     @Test
-    public void testGetMonitor_returnsMonitor() throws Exception {
+    public void testGetMonitor_returnsMonitor() {
         IBackupManagerMonitor monitor = mReporter.getMonitor();
 
         assertThat(monitor).isEqualTo(mMonitor);
     }
 
     @Test
-    public void testGetObserver_returnsObserver() throws Exception {
+    public void testGetObserver_returnsObserver() {
         IBackupObserver observer = mReporter.getObserver();
 
         assertThat(observer).isEqualTo(mObserver);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 44986a0..a69f007 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -117,9 +117,6 @@
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
@@ -137,6 +134,7 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
@@ -159,10 +157,8 @@
 import java.util.stream.Stream;
 
 // TODO: Test agents timing out
-@RunWith(FrameworkRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 @Config(
-        manifest = Config.NONE,
-        sdk = 26,
         shadows = {
             FrameworkShadowLooper.class,
             ShadowBackupDataInput.class,
@@ -170,8 +166,6 @@
             ShadowEventLog.class,
             ShadowQueuedWork.class,
         })
-@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
-@SystemLoaderClasses({IBackupTransport.class, IBackupAgent.class, PackageInfo.class})
 @Presubmit
 public class KeyValueBackupTaskTest {
     private static final PackageData PACKAGE_1 = keyValuePackage(1);
@@ -190,6 +184,7 @@
     private Handler mBackupHandler;
     private PowerManager.WakeLock mWakeLock;
     private KeyValueBackupReporter mReporter;
+    private PackageManager mPackageManager;
     private ShadowPackageManager mShadowPackageManager;
     private FakeIBackupManager mBackupManager;
     private File mBaseStateDir;
@@ -222,8 +217,8 @@
         mDataDir.mkdirs();
         assertThat(mDataDir.isDirectory()).isTrue();
 
-        PackageManager packageManager = mApplication.getPackageManager();
-        mShadowPackageManager = shadowOf(packageManager);
+        mPackageManager = mApplication.getPackageManager();
+        mShadowPackageManager = shadowOf(mPackageManager);
 
         mWakeLock = createBackupWakeLock(mApplication);
         mBackupManager = spy(FakeIBackupManager.class);
@@ -238,7 +233,7 @@
                 mBackupManagerService,
                 mApplication,
                 mTransportManager,
-                packageManager,
+                mPackageManager,
                 mBackupManagerService.getBackupHandler(),
                 mWakeLock,
                 mBackupManagerService.getAgentTimeoutParameters());
@@ -2443,7 +2438,7 @@
 
     private AgentMock setUpAgent(PackageData packageData) {
         try {
-            mShadowPackageManager.setApplicationEnabledSetting(
+            mPackageManager.setApplicationEnabledSetting(
                     packageData.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
             PackageInfo packageInfo = getPackageInfo(packageData);
             mShadowPackageManager.addPackage(packageInfo);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
index 4b79657..3698b79 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
@@ -23,18 +23,13 @@
 import android.app.backup.BackupTransport;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TaskExceptionTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
index f3621e2..5ac26f4 100644
--- a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
@@ -20,18 +20,13 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.concurrent.CompletableFuture;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class FutureBackupCallbackTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
index 1d92bed..7ec2a4e 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
@@ -32,23 +32,19 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.backup.testing.TestUtils.ThrowingRunnable;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RemoteCallTest {
     /** A {@link RemoteCallable} that calls the callback immediately. */
@@ -267,9 +263,4 @@
     private static void postDelayed(Handler handler, ThrowingRunnable runnable, long delayMillis) {
         handler.postDelayed(() -> uncheck(runnable), delayMillis);
     }
-
-    /** Unchecked version of {@link Handler#post(Runnable)}. */
-    private static void post(Handler handler, ThrowingRunnable runnable) {
-        handler.post(() -> uncheck(runnable));
-    }
 }
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
index 7f6fd57..b9a77fb 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
@@ -22,16 +22,11 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RemoteResultTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
index e0d3c0c..38a54da 100644
--- a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
@@ -22,16 +22,11 @@
 import android.app.backup.IBackupManager;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ServiceBackupCallbackTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index 2717120..0e2b95b 100644
--- a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -19,7 +19,6 @@
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
-
 import static com.android.server.backup.testing.TestUtils.assertEventLogged;
 import static com.android.server.backup.testing.TestUtils.assertEventNotLogged;
 import static com.android.server.backup.testing.TransportData.backupTransport;
@@ -58,8 +57,6 @@
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowEventLog;
 import com.android.server.testing.shadows.ShadowPerformUnifiedRestoreTask;
 
@@ -69,6 +66,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
@@ -78,18 +76,14 @@
 
 import java.util.ArrayDeque;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
 @Presubmit
 public class ActiveRestoreSessionTest {
     private static final String PACKAGE_1 = "com.example.package1";
     private static final String PACKAGE_2 = "com.example.package2";
-    public static final long TOKEN_1 = 1L;
-    public static final long TOKEN_2 = 2L;
+    private static final long TOKEN_1 = 1L;
+    private static final long TOKEN_2 = 2L;
 
     @Mock private BackupManagerService mBackupManagerService;
     @Mock private TransportManager mTransportManager;
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
index bbec7af..7dd0d92 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
@@ -17,6 +17,7 @@
 package com.android.server.backup.transport;
 
 import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.argThat;
@@ -32,19 +33,15 @@
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportClientManagerTest {
     private static final String PACKAGE_NAME = "random.package.name";
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index f843b50..7281a3c 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -49,8 +49,6 @@
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowCloseGuard;
 import com.android.server.testing.shadows.ShadowEventLog;
@@ -62,6 +60,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLog;
 import org.robolectric.shadows.ShadowLooper;
@@ -69,17 +68,13 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Supplier;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
             ShadowEventLog.class,
             ShadowCloseGuard.class,
             ShadowSlog.class,
             FrameworkShadowLooper.class
         })
-@SystemLoaderPackages({"com.android.server.backup"})
 @Presubmit
 public class TransportClientTest {
     private static final String PACKAGE_NAME = "some.package.name";
@@ -137,7 +132,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsBindService() throws Exception {
+    public void testConnectAsync_callsBindService() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
 
         verify(mContext)
@@ -149,7 +144,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsListenerWhenConnected() throws Exception {
+    public void testConnectAsync_callsListenerWhenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -161,8 +156,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenPendingConnection_callsAllListenersWhenConnected()
-            throws Exception {
+    public void testConnectAsync_whenPendingConnection_callsAllListenersWhenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -177,7 +171,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenAlreadyConnected_callsListener() throws Exception {
+    public void testConnectAsync_whenAlreadyConnected_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -190,7 +184,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenFrameworkDoesntBind_callsListener() throws Exception {
+    public void testConnectAsync_whenFrameworkDoesntBind_callsListener() {
         when(mContext.bindServiceAsUser(
                         eq(mBindIntent),
                         any(ServiceConnection.class),
@@ -206,7 +200,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() throws Exception {
+    public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() {
         when(mContext.bindServiceAsUser(
                         eq(mBindIntent),
                         any(ServiceConnection.class),
@@ -221,8 +215,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnServiceDisconnectedBeforeNewConnection_callsListener()
-            throws Exception {
+    public void testConnectAsync_afterOnServiceDisconnectedBeforeNewConnection_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -235,8 +228,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnServiceDisconnectedAfterNewConnection_callsListener()
-            throws Exception {
+    public void testConnectAsync_afterOnServiceDisconnectedAfterNewConnection_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -251,7 +243,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsListenerIfBindingDies() throws Exception {
+    public void testConnectAsync_callsListenerIfBindingDies() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -263,8 +255,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenPendingConnection_callsListenersIfBindingDies()
-            throws Exception {
+    public void testConnectAsync_whenPendingConnection_callsListenersIfBindingDies() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -412,14 +403,14 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenCreated() throws Throwable {
+    public void testMarkAsDisposed_whenCreated() {
         mTransportClient.markAsDisposed();
 
         // No exception thrown
     }
 
     @Test
-    public void testMarkAsDisposed_afterOnBindingDied() throws Throwable {
+    public void testMarkAsDisposed_afterOnBindingDied() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onBindingDied(mTransportComponent);
@@ -430,7 +421,7 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenConnectedAndUnbound() throws Throwable {
+    public void testMarkAsDisposed_whenConnectedAndUnbound() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -442,7 +433,7 @@
     }
 
     @Test
-    public void testMarkAsDisposed_afterOnServiceDisconnected() throws Throwable {
+    public void testMarkAsDisposed_afterOnServiceDisconnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -454,14 +445,14 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenBound() throws Throwable {
+    public void testMarkAsDisposed_whenBound() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
 
         expectThrows(RuntimeException.class, mTransportClient::markAsDisposed);
     }
 
     @Test
-    public void testMarkAsDisposed_whenConnected() throws Throwable {
+    public void testMarkAsDisposed_whenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
index 322db85c..f01a6b0 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
@@ -25,17 +25,13 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.backup.transport.TransportStats.Stats;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportStatsTest {
     private static final double TOLERANCE = 0.0001;
diff --git a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
index 5046094..d58c3f7 100644
--- a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
@@ -1,9 +1,10 @@
 package com.android.server.location;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -11,27 +12,18 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssBatchingProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        shadows = {
-        },
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssBatchingProviderTest {
 
diff --git a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
index 187303c..beb5941 100644
--- a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
@@ -1,8 +1,8 @@
 package com.android.server.location;
 
-import static org.mockito.Matchers.anyDouble;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyDouble;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -11,25 +11,17 @@
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssGeofenceProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssGeofenceProviderTest {
     private static final int GEOFENCE_ID = 12345;
diff --git a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
index 23d6cf6..b349b67 100644
--- a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
@@ -1,6 +1,7 @@
 package com.android.server.location;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -10,26 +11,18 @@
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 /**
  * Unit tests for {@link GnssMeasurementsProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssMeasurementsProviderTest {
     @Mock
diff --git a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
index 8d3de3c..59e9a15 100644
--- a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
@@ -10,25 +10,17 @@
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssNavigationMessageProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssNavigationMessageProviderTest {
     @Mock
diff --git a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java b/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
index e6d53551..f37f50e 100644
--- a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
+++ b/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
@@ -4,24 +4,16 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.HashSet;
 
 /**
  * Unit tests for {@link GnssPositionMode}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssPositionModeTest {
 
diff --git a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
index d6f5446..ba4a753 100644
--- a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
+++ b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
@@ -2,7 +2,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
@@ -13,18 +13,15 @@
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 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.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
 
 import java.util.Collection;
 import java.util.List;
@@ -32,18 +29,10 @@
 /**
  * Unit tests for {@link GnssSatelliteBlacklistHelper}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        shadows = {
-        },
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssSatelliteBlacklistHelperTest {
 
-    private Context mContext;
     private ContentResolver mContentResolver;
     @Mock
     private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback mCallback;
@@ -51,9 +40,9 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mContentResolver = mContext.getContentResolver();
-        new GnssSatelliteBlacklistHelper(mContext, Looper.myLooper(), mCallback);
+        Context context = RuntimeEnvironment.application;
+        mContentResolver = context.getContentResolver();
+        new GnssSatelliteBlacklistHelper(context, Looper.myLooper(), mCallback);
     }
 
     @Test
diff --git a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
index a68b579..aac0a34 100644
--- a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
+++ b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
@@ -9,16 +9,14 @@
 import android.util.NtpTrustedTime;
 
 import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 import org.robolectric.shadows.ShadowSystemClock;
 
@@ -28,12 +26,7 @@
 /**
  * Unit tests for {@link NtpTimeHelper}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class NtpTimeHelperTest {
 
diff --git a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java b/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
deleted file mode 100644
index d2a4d06..0000000
--- a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.testing;
-
-import static java.util.Arrays.asList;
-
-import com.google.common.collect.ImmutableSet;
-
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.internal.SandboxFactory;
-import org.robolectric.internal.SdkEnvironment;
-import org.robolectric.internal.bytecode.InstrumentationConfiguration;
-import org.robolectric.internal.bytecode.SandboxClassLoader;
-import org.robolectric.util.Util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Stream;
-
-import javax.annotation.Nonnull;
-
-/**
- * HACK
- * Robolectric loads up Android environment from prebuilt android jars before running a method.
- * These jars are versioned according to the SDK level configured for the method (or class). The
- * jars represent a snapshot of the Android APIs in that SDK level. For Robolectric tests that are
- * testing Android components themselves we don't want certain classes (usually the
- * class-under-test) to be loaded from the prebuilt jar, we want it instead to be loaded from the
- * dependencies of our test target, i.e. the system class loader. That way we can write tests
- * against the actual classes that are in the tree, not a past version of them. Ideally we would
- * have a locally built jar referenced by Robolectric, but until that happens one can use this
- * class.
- * This class reads the {@link SystemLoaderClasses} or {@link SystemLoaderPackages} annotations on
- * test classes, for classes that match the annotations it will bypass the android jar and load it
- * from the system class loader. Allowing the test to test the actual class in the tree.
- *
- * Implementation note: One could think about overriding
- * {@link RobolectricTestRunner#createClassLoaderConfig(FrameworkMethod)} method and putting the
- * classes in the annotation in the {@link InstrumentationConfiguration} list of classes not to
- * acquire. Unfortunately, this will not work because we will not be instrumenting the class.
- * Instead, we have to load the class bytes from the system class loader but still instrument it, we
- * do this by overriding {@link SandboxClassLoader#getByteCode(String)} and loading the class bytes
- * from the system class loader if it in the {@link SystemLoaderClasses} annotation. This way the
- * {@link SandboxClassLoader} still instruments the class, but it's not loaded from the android jar.
- * Finally, we inject the custom class loader in place of the default one.
- *
- * TODO: Remove this when we are using locally built android jars in the method's environment.
- */
-public class FrameworkRobolectricTestRunner extends RobolectricTestRunner {
-    private final SandboxFactory mSandboxFactory;
-
-    public FrameworkRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-        Set<String> classPrefixes = getSystemLoaderClassPrefixes(testClass);
-        mSandboxFactory = new FrameworkSandboxFactory(classPrefixes);
-    }
-
-    private Set<String> getSystemLoaderClassPrefixes(Class<?> testClass) {
-        Set<String> classPrefixes = new HashSet<>();
-        SystemLoaderClasses byClass = testClass.getAnnotation(SystemLoaderClasses.class);
-        if (byClass != null) {
-            Stream.of(byClass.value()).map(Class::getName).forEach(classPrefixes::add);
-        }
-        SystemLoaderPackages byPackage = testClass.getAnnotation(SystemLoaderPackages.class);
-        if (byPackage != null) {
-            classPrefixes.addAll(asList(byPackage.value()));
-        }
-        return classPrefixes;
-    }
-
-    @Nonnull
-    @Override
-    protected SdkEnvironment getSandbox(FrameworkMethod method) {
-        // HACK: Calling super just to get SdkConfig via sandbox.getSdkConfig(), because
-        // RobolectricFrameworkMethod, the runtime class of method, is package-protected
-        SdkEnvironment sandbox = super.getSandbox(method);
-        return mSandboxFactory.getSdkEnvironment(
-                createClassLoaderConfig(method),
-                getJarResolver(),
-                sandbox.getSdkConfig());
-    }
-
-    private static class FrameworkClassLoader extends SandboxClassLoader {
-        private final Set<String> mSystemLoaderClassPrefixes;
-
-        private FrameworkClassLoader(
-                Set<String> systemLoaderClassPrefixes,
-                ClassLoader systemClassLoader,
-                InstrumentationConfiguration instrumentationConfig,
-                URL... urls) {
-            super(systemClassLoader, instrumentationConfig, urls);
-            mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
-        }
-
-        @Override
-        protected byte[] getByteCode(String className) throws ClassNotFoundException {
-            String classFileName = className.replace('.', '/') + ".class";
-            if (shouldLoadFromSystemLoader(className)) {
-                try (InputStream classByteStream = getResourceAsStream(classFileName)) {
-                    if (classByteStream == null) {
-                        throw new ClassNotFoundException(className);
-                    }
-                    return Util.readBytes(classByteStream);
-                } catch (IOException e) {
-                    throw new ClassNotFoundException(
-                            "Couldn't load " + className + " from system class loader", e);
-                }
-            }
-            return super.getByteCode(className);
-        }
-
-        /**
-         * HACK^2
-         * The framework Robolectric run configuration puts a prebuilt in front of us, so we try not
-         * to load the class from there, if possible.
-         */
-        @Override
-        public InputStream getResourceAsStream(String resource) {
-            try {
-                Enumeration<URL> urls = getResources(resource);
-                while (urls.hasMoreElements()) {
-                    URL url = urls.nextElement();
-                    if (!url.toString().toLowerCase().contains("prebuilt")) {
-                        return url.openStream();
-                    }
-                }
-            } catch (IOException e) {
-                // Fall through
-            }
-            return super.getResourceAsStream(resource);
-        }
-
-        /**
-         * Classes like com.package.ClassName$InnerClass should also be loaded from the system class
-         * loader, so we test if the classes in the annotation are prefixes of the class to load.
-         */
-        private boolean shouldLoadFromSystemLoader(String className) {
-            for (String classPrefix : mSystemLoaderClassPrefixes) {
-                if (className.startsWith(classPrefix)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    private static class FrameworkSandboxFactory extends SandboxFactory {
-        private final Set<String> mSystemLoaderClassPrefixes;
-
-        private FrameworkSandboxFactory(Set<String> systemLoaderClassPrefixes) {
-            mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
-        }
-
-        @Nonnull
-        @Override
-        public ClassLoader createClassLoader(
-                InstrumentationConfiguration instrumentationConfig, URL... urls) {
-            return new FrameworkClassLoader(
-                    mSystemLoaderClassPrefixes,
-                    ClassLoader.getSystemClassLoader(),
-                    instrumentationConfig,
-                    urls);
-        }
-    }
-}
diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java b/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java
deleted file mode 100644
index 646a413..0000000
--- a/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.testing;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}.
- * This will make the classes specified be loaded from the system class loader, NOT from the
- * Robolectric android jar.
- *
- * @see FrameworkRobolectricTestRunner
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SystemLoaderClasses {
-    Class<?>[] value() default {};
-}
diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java b/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
deleted file mode 100644
index e01c0a4..0000000
--- a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.testing;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}.
- * This will make the classes under the specified packages be loaded from the system class loader,
- * NOT from the Robolectric android jar.
- *
- * @see FrameworkRobolectricTestRunner
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SystemLoaderPackages {
-    String[] value() default {};
-}
diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java
deleted file mode 100644
index 6d22073..0000000
--- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.testing.shadows;
-
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.UserHandle;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowContextImpl;
-
-@Implements(className = ShadowContextImpl.CLASS_NAME, inheritImplementationMethods = true)
-public class FrameworkShadowContextImpl extends ShadowContextImpl {
-    @Implementation
-    public boolean bindServiceAsUser(
-            Intent service,
-            ServiceConnection connection,
-            int flags,
-            UserHandle user) {
-        return bindService(service, connection, flags);
-    }
-}
diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
index c0eeb38..16d16cd 100644
--- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
+++ b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
@@ -25,7 +25,7 @@
 
 import java.util.Optional;
 
-@Implements(value = Looper.class, inheritImplementationMethods = true)
+@Implements(value = Looper.class)
 public class FrameworkShadowLooper extends ShadowLooper {
     @RealObject private Looper mLooper;
     private Optional<Boolean> mIsCurrentThread = Optional.empty();
@@ -39,7 +39,7 @@
     }
 
     @Implementation
-    public boolean isCurrentThread() {
+    protected boolean isCurrentThread() {
         if (mIsCurrentThread.isPresent()) {
             return mIsCurrentThread.get();
         }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
index 21faa09..5fffb14 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
@@ -26,6 +26,7 @@
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -52,21 +53,22 @@
     }
 
     @Implementation
-    public static boolean appIsRunningAndEligibleForBackupWithTransport(
+    protected static boolean appIsRunningAndEligibleForBackupWithTransport(
             @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
         return sAppsRunningAndEligibleForBackupWithTransport.contains(packageName);
     }
 
     @Implementation
-    public static boolean appIsEligibleForBackup(ApplicationInfo app, PackageManager pm) {
+    protected static boolean appIsEligibleForBackup(ApplicationInfo app, PackageManager pm) {
         return sAppsEligibleForBackup.contains(app.packageName);
     }
 
     @Implementation
-    public static boolean appGetsFullBackup(PackageInfo packageInfo) {
+    protected static boolean appGetsFullBackup(PackageInfo packageInfo) {
         return sAppsGetFullBackup.contains(packageInfo.packageName);
     }
 
+    @Resetter
     public static void reset() {
         sAppsRunningAndEligibleForBackupWithTransport.clear();
         sAppsEligibleForBackup.clear();
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
index 4901828..e7d2a68 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
@@ -52,12 +52,12 @@
     private boolean mHeaderReady;
 
     @Implementation
-    public void __constructor__(FileDescriptor fd) {
+    protected void __constructor__(FileDescriptor fd) {
         mFileDescriptor = fd;
     }
 
     @Implementation
-    public boolean readNextHeader() throws IOException {
+    protected boolean readNextHeader() throws IOException {
         if (sReadNextHeaderThrow) {
             sReadNextHeaderThrow = false;
             throw new IOException("Fake exception");
@@ -75,19 +75,19 @@
     }
 
     @Implementation
-    public String getKey() {
+    protected String getKey() {
         checkHeaderReady();
         return mKey;
     }
 
     @Implementation
-    public int getDataSize() {
+    protected int getDataSize() {
         checkHeaderReady();
         return mSize;
     }
 
     @Implementation
-    public int readEntityData(byte[] data, int offset, int size) throws IOException {
+    protected int readEntityData(byte[] data, int offset, int size) throws IOException {
         checkHeaderReady();
         int result = mInput.read(data, offset, size);
         if (result < 0) {
@@ -97,7 +97,7 @@
     }
 
     @Implementation
-    public void skipEntityData() throws IOException {
+    protected void skipEntityData() throws IOException {
         checkHeaderReady();
         mInput.read(new byte[mSize], 0, mSize);
     }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
index 5812c3c..4aef28c 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
@@ -39,19 +39,19 @@
     private int mTransportFlags;
 
     @Implementation
-    public void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
+    protected void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
         mFileDescriptor = fd;
         mQuota = quota;
         mTransportFlags = transportFlags;
     }
 
     @Implementation
-    public long getQuota() {
+    protected long getQuota() {
         return mQuota;
     }
 
     @Implementation
-    public int getTransportFlags() {
+    protected int getTransportFlags() {
         return mTransportFlags;
     }
 
@@ -61,7 +61,7 @@
     }
 
     @Implementation
-    public int writeEntityHeader(String key, int dataSize) throws IOException {
+    protected int writeEntityHeader(String key, int dataSize) throws IOException {
         ensureOutput();
         final int size;
         try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
@@ -81,7 +81,7 @@
     }
 
     @Implementation
-    public int writeEntityData(byte[] data, int size) throws IOException {
+    protected int writeEntityData(byte[] data, int size) throws IOException {
         ensureOutput();
         mOutput.write(data, 0, size);
         mOutput.flush();
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
index 043d44b..1ece49e 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
@@ -17,6 +17,7 @@
 package com.android.server.testing.shadows;
 
 import android.os.Binder;
+
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -31,14 +32,14 @@
     private static Integer originalCallingUid;
 
     @Implementation
-    public static long clearCallingIdentity() {
+    protected static long clearCallingIdentity() {
         originalCallingUid = getCallingUid();
         setCallingUid(LOCAL_UID);
         return 1L;
     }
 
     @Implementation
-    public static void restoreCallingIdentity(long token) {
+    protected static void restoreCallingIdentity(long token) {
         setCallingUid(originalCallingUid);
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
index 3df1723..5d9c88b 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
@@ -32,14 +32,14 @@
     private static final LinkedHashSet<Entry> ENTRIES = new LinkedHashSet<>();
 
     @Implementation
-    public static int writeEvent(int tag, Object... values) {
+    protected static int writeEvent(int tag, Object... values) {
         ENTRIES.add(new Entry(tag, Arrays.asList(values)));
         // Currently we don't care about the return value, if we do, estimate it correctly
         return 0;
     }
 
     @Implementation
-    public static int writeEvent(int tag, String string) {
+    protected static int writeEvent(int tag, String string) {
         return writeEvent(tag, (Object) string);
     }
 
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
index 3c913e3..4756476 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
@@ -31,7 +31,7 @@
      * implementation.
      */
     @Implementation
-    public static int backupToTar(
+    protected static int backupToTar(
             String packageName,
             String domain,
             String linkdomain,
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
index 3941f17..23c44b0e 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
@@ -18,8 +18,10 @@
 
 import android.content.Context;
 import android.os.Binder;
+
 import com.android.server.backup.BackupManagerConstants;
 import com.android.server.backup.KeyValueBackupJob;
+
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -32,7 +34,7 @@
     }
 
     @Implementation
-    public static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
+    protected static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
         callingUid = Binder.getCallingUid();
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
index b7db56b..ca80664 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
@@ -53,7 +53,7 @@
     private List<String> mPendingFullBackups;
 
     @Implementation
-    public void __constructor__(
+    protected void __constructor__(
             BackupManagerService backupManagerService,
             TransportClient transportClient,
             String transportDirName,
@@ -71,7 +71,7 @@
     }
 
     @Implementation
-    public void execute() {
+    protected void execute() {
         mListener.onFinished("ShadowKeyValueBackupTask.execute()");
     }
 
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
index 0f93c7a..228d4eb 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
@@ -54,7 +54,7 @@
     private OnTaskFinishedListener mListener;
 
     @Implementation
-    public void __constructor__(
+    protected void __constructor__(
             BackupManagerService backupManagerService,
             TransportClient transportClient,
             IRestoreObserver observer,
@@ -74,7 +74,7 @@
     }
 
     @Implementation
-    public void execute() {
+    protected void execute() {
         mBackupManagerService.setRestoreInProgress(false);
         mListener.onFinished("ShadowPerformUnifiedRestoreTask.execute()");
     }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java b/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
index 737b0c8..32ef1bc 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
@@ -21,92 +21,91 @@
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowLog;
 
 @Implements(Slog.class)
 public class ShadowSlog {
     @Implementation
-    public static int v(String tag, String msg) {
+    protected static int v(String tag, String msg) {
         return Log.v(tag, msg);
     }
 
     @Implementation
-    public static int v(String tag, String msg, Throwable tr) {
+    protected static int v(String tag, String msg, Throwable tr) {
         return Log.v(tag, msg, tr);
     }
 
     @Implementation
-    public static int d(String tag, String msg) {
+    protected static int d(String tag, String msg) {
         return Log.d(tag, msg);
     }
 
     @Implementation
-    public static int d(String tag, String msg, Throwable tr) {
+    protected static int d(String tag, String msg, Throwable tr) {
         return Log.d(tag, msg, tr);
     }
 
     @Implementation
-    public static int i(String tag, String msg) {
+    protected static int i(String tag, String msg) {
         return Log.i(tag, msg);
     }
 
     @Implementation
-    public static int i(String tag, String msg, Throwable tr) {
+    protected static int i(String tag, String msg, Throwable tr) {
         return Log.i(tag, msg, tr);
     }
 
     @Implementation
-    public static int w(String tag, String msg) {
+    protected static int w(String tag, String msg) {
         return Log.w(tag, msg);
     }
 
     @Implementation
-    public static int w(String tag, String msg, Throwable tr) {
+    protected static int w(String tag, String msg, Throwable tr) {
         return Log.w(tag, msg, tr);
     }
 
     @Implementation
-    public static int w(String tag, Throwable tr) {
+    protected static int w(String tag, Throwable tr) {
         return Log.w(tag, tr);
     }
 
     @Implementation
-    public static int e(String tag, String msg) {
+    protected static int e(String tag, String msg) {
         return Log.e(tag, msg);
     }
 
     @Implementation
-    public static int e(String tag, String msg, Throwable tr) {
+    protected static int e(String tag, String msg, Throwable tr) {
         return Log.e(tag, msg, tr);
     }
 
     @Implementation
-    public static int wtf(String tag, String msg) {
+    protected static int wtf(String tag, String msg) {
         return Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static void wtfQuiet(String tag, String msg) {
+    protected static void wtfQuiet(String tag, String msg) {
         Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static int wtfStack(String tag, String msg) {
+    protected static int wtfStack(String tag, String msg) {
         return Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static int wtf(String tag, Throwable tr) {
+    protected static int wtf(String tag, Throwable tr) {
         return Log.wtf(tag, tr);
     }
 
     @Implementation
-    public static int wtf(String tag, String msg, Throwable tr) {
+    protected static int wtf(String tag, String msg, Throwable tr) {
         return Log.wtf(tag, msg, tr);
     }
 
     @Implementation
-    public static int println(int priority, String tag, String msg) {
+    protected static int println(int priority, String tag, String msg) {
         return Log.println(priority, tag, msg);
     }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a188ef6..bd1a0fb 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -9361,4 +9361,55 @@
         }
         return false;
     }
+
+    /**
+     * Set preferred opportunistic data subscription id.
+     *
+     * <p>Requires that the calling app has carrier privileges on both primary and
+     * secondary subscriptions (see
+     * {@link #hasCarrierPrivileges}), or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param subId which opportunistic subscription
+     * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
+     * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+     * @return true if request is accepted, else false.
+     *
+     */
+    public boolean setPreferredOpportunisticDataSubscription(int subId) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        try {
+            IAns iAlternativeNetworkService = getIAns();
+            if (iAlternativeNetworkService != null) {
+                return iAlternativeNetworkService.setPreferredData(subId, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setPreferredData RemoteException", ex);
+        }
+        return false;
+    }
+
+    /**
+     * Get preferred opportunistic data subscription Id
+     *
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}),
+     * or has permission {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
+     * @return subId preferred opportunistic subscription id or
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred
+     * subscription id
+     *
+     */
+    public int getPreferredOpportunisticDataSubscription() {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        try {
+            IAns iAlternativeNetworkService = getIAns();
+            if (iAlternativeNetworkService != null) {
+                subId = iAlternativeNetworkService.getPreferredData(pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getPreferredData RemoteException", ex);
+        }
+        return subId;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/IAns.aidl b/telephony/java/com/android/internal/telephony/IAns.aidl
index 6eb8d66..e9a4649 100755
--- a/telephony/java/com/android/internal/telephony/IAns.aidl
+++ b/telephony/java/com/android/internal/telephony/IAns.aidl
@@ -49,4 +49,33 @@
     * @param callingPackage caller's package name
     */
     boolean isEnabled(String callingPackage);
+
+    /**
+     * Set preferred opportunistic data subscription id.
+     *
+     * <p>Requires that the calling app has carrier privileges on both primary and
+     * secondary subscriptions (see
+     * {@link #hasCarrierPrivileges}), or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param subId which opportunistic subscription
+     * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
+     * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+     * @param callingPackage caller's package name
+     * @return true if request is accepted, else false.
+     *
+     */
+    boolean setPreferredData(int subId, String callingPackage);
+
+    /**
+     * Get preferred opportunistic data subscription Id
+     *
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}),
+     * or has permission {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
+     * @return subId preferred opportunistic subscription id or
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred
+     * subscription id
+     *
+     */
+    int getPreferredData(String callingPackage);
 }