Merge "Add Log.wtf when transitionTo is used improperly"
diff --git a/api/system-current.txt b/api/system-current.txt
index c81f4e9..6db91c6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40610,6 +40610,7 @@
     method public boolean isSmsCapable();
     method public boolean isTtyModeSupported();
     method public boolean isVideoCallingEnabled();
+    method public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isVoiceCapable();
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
@@ -40623,6 +40624,7 @@
     method public boolean setPreferredNetworkTypeToGlobal();
     method public boolean setRadio(boolean);
     method public boolean setRadioPower(boolean);
+    method public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
     method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
     method public void silenceRinger();
     method public boolean supplyPin(java.lang.String);
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 54c3d1a..beb550c 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -77,12 +77,23 @@
 static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
 static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound";
 static const int ANIM_ENTRY_NAME_MAX = 256;
+static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed";
+static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason";
+// bootreasons list in "system/core/bootstat/bootstat.cpp".
+static const std::vector<std::string> PLAY_SOUND_BOOTREASON_BLACKLIST {
+  "kernel_panic",
+  "Panic",
+  "Watchdog",
+};
 
 // ---------------------------------------------------------------------------
 
 BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
         mTimeCheckThread(NULL) {
     mSession = new SurfaceComposerClient();
+
+    // If the system has already booted, the animation is not being used for a boot.
+    mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
 }
 
 BootAnimation::~BootAnimation() {}
@@ -776,13 +787,9 @@
                 break;
 
             // only play audio file the first time we animate the part
-            if (r == 0 && part.audioData) {
-                // Read the system property to see if we should play the sound.
-                // If not present, default to playing it.
-                if (property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
-                    ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
-                    audioplay::playClip(part.audioData, part.audioLength);
-                }
+            if (r == 0 && part.audioData && playSoundsAllowed()) {
+                ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
+                audioplay::playClip(part.audioData, part.audioLength);
             }
 
             glClearColor(
@@ -918,6 +925,30 @@
     return animation;
 }
 
+bool BootAnimation::playSoundsAllowed() const {
+    // Only play sounds for system boots, not runtime restarts.
+    if (!mSystemBoot) {
+        return false;
+    }
+
+    // Read the system property to see if we should play the sound.
+    // If it's not present, default to allowed.
+    if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
+        return false;
+    }
+
+    // Don't play sounds if this is a reboot due to an error.
+    char bootreason[PROPERTY_VALUE_MAX];
+    if (property_get(BOOTREASON_PROP_NAME, bootreason, nullptr) > 0) {
+        for (const auto& str : PLAY_SOUND_BOOTREASON_BLACKLIST) {
+            if (strcasecmp(str.c_str(), bootreason) == 0) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
 bool BootAnimation::updateIsTimeAccurate() {
     static constexpr long long MAX_TIME_IN_PAST =   60000LL * 60LL * 24LL * 30LL;  // 30 days
     static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL;  // 90 minutes
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index a53216e..fd497a3 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -120,6 +120,7 @@
     void releaseAnimation(Animation*) const;
     bool parseAnimationDesc(Animation&);
     bool preloadZip(Animation &animation);
+    bool playSoundsAllowed() const;
 
     void checkExit();
 
@@ -137,6 +138,7 @@
     sp<Surface> mFlingerSurface;
     bool        mClockEnabled;
     bool        mTimeIsAccurate;
+    bool        mSystemBoot;
     String8     mZipFileName;
     SortedVector<String8> mLoadedFiles;
     sp<TimeCheckThread> mTimeCheckThread;
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
index 94214ff..633dd97 100644
--- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
@@ -52,7 +52,7 @@
                 IWifiManager wifiMgr
                         = IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
                 try {
-                    wifiMgr.setWifiEnabled(flag);
+                    wifiMgr.setWifiEnabled("com.android.shell", flag);
                 }
                 catch (RemoteException e) {
                     System.err.println("Wi-Fi operation failed: " + e);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index ae78e218..c4eaccc 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -628,8 +628,8 @@
         if (connection == null) {
             return false;
         }
-        List<MotionEvent> events = MotionEventGenerator.getMotionEventsFromGestureDescription(
-                gesture, 100);
+        List<GestureDescription.GestureStep> steps =
+                MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 100);
         try {
             synchronized (mLock) {
                 mGestureStatusCallbackSequence++;
@@ -641,8 +641,8 @@
                             callback, handler);
                     mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo);
                 }
-                connection.sendMotionEvents(mGestureStatusCallbackSequence,
-                        new ParceledListSlice<>(events));
+                connection.sendGesture(mGestureStatusCallbackSequence,
+                        new ParceledListSlice<>(steps));
             }
         } catch (RemoteException re) {
             throw new RuntimeException(re);
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index fc9581e..d9b03fa 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -21,6 +21,8 @@
 import android.graphics.Path;
 import android.graphics.PathMeasure;
 import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
@@ -303,13 +305,37 @@
         }
     }
 
-    private static class TouchPoint {
+    /**
+     * The location of a finger for gesture dispatch
+     *
+     * @hide
+     */
+    public static class TouchPoint implements Parcelable {
+        private static final int FLAG_IS_START_OF_PATH = 0x01;
+        private static final int FLAG_IS_END_OF_PATH = 0x02;
+
         int mPathIndex;
         boolean mIsStartOfPath;
         boolean mIsEndOfPath;
         float mX;
         float mY;
 
+        public TouchPoint() {
+        }
+
+        public TouchPoint(TouchPoint pointToCopy) {
+            copyFrom(pointToCopy);
+        }
+
+        public TouchPoint(Parcel parcel) {
+            mPathIndex = parcel.readInt();
+            int startEnd = parcel.readInt();
+            mIsStartOfPath = (startEnd & FLAG_IS_START_OF_PATH) != 0;
+            mIsEndOfPath = (startEnd & FLAG_IS_END_OF_PATH) != 0;
+            mX = parcel.readFloat();
+            mY = parcel.readFloat();
+        }
+
         void copyFrom(TouchPoint other) {
             mPathIndex = other.mPathIndex;
             mIsStartOfPath = other.mIsStartOfPath;
@@ -317,12 +343,94 @@
             mX = other.mX;
             mY = other.mY;
         }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(mPathIndex);
+            int startEnd = mIsStartOfPath ? FLAG_IS_START_OF_PATH : 0;
+            startEnd |= mIsEndOfPath ? FLAG_IS_END_OF_PATH : 0;
+            dest.writeInt(startEnd);
+            dest.writeFloat(mX);
+            dest.writeFloat(mY);
+        }
+
+        public static final Parcelable.Creator<TouchPoint> CREATOR
+                = new Parcelable.Creator<TouchPoint>() {
+            public TouchPoint createFromParcel(Parcel in) {
+                return new TouchPoint(in);
+            }
+
+            public TouchPoint[] newArray(int size) {
+                return new TouchPoint[size];
+            }
+        };
+    }
+
+    /**
+     * A step along a gesture. Contains all of the touch points at a particular time
+     *
+     * @hide
+     */
+    public static class GestureStep implements Parcelable {
+        public long timeSinceGestureStart;
+        public int numTouchPoints;
+        public TouchPoint[] touchPoints;
+
+        public GestureStep(long timeSinceGestureStart, int numTouchPoints,
+                TouchPoint[] touchPointsToCopy) {
+            this.timeSinceGestureStart = timeSinceGestureStart;
+            this.numTouchPoints = numTouchPoints;
+            this.touchPoints = new TouchPoint[numTouchPoints];
+            for (int i = 0; i < numTouchPoints; i++) {
+                this.touchPoints[i] = new TouchPoint(touchPointsToCopy[i]);
+            }
+        }
+
+        public GestureStep(Parcel parcel) {
+            timeSinceGestureStart = parcel.readLong();
+            Parcelable[] parcelables =
+                    parcel.readParcelableArray(TouchPoint.class.getClassLoader());
+            numTouchPoints = (parcelables == null) ? 0 : parcelables.length;
+            touchPoints = new TouchPoint[numTouchPoints];
+            for (int i = 0; i < numTouchPoints; i++) {
+                touchPoints[i] = (TouchPoint) parcelables[i];
+            }
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeLong(timeSinceGestureStart);
+            dest.writeParcelableArray(touchPoints, flags);
+        }
+
+        public static final Parcelable.Creator<GestureStep> CREATOR
+                = new Parcelable.Creator<GestureStep>() {
+            public GestureStep createFromParcel(Parcel in) {
+                return new GestureStep(in);
+            }
+
+            public GestureStep[] newArray(int size) {
+                return new GestureStep[size];
+            }
+        };
     }
 
     /**
      * Class to convert a GestureDescription to a series of MotionEvents.
+     *
+     * @hide
      */
-    static class MotionEventGenerator {
+    public static class MotionEventGenerator {
         /**
          * Constants used to initialize all MotionEvents
          */
@@ -341,39 +449,53 @@
         private static PointerCoords[] sPointerCoords;
         private static PointerProperties[] sPointerProps;
 
-        static List<MotionEvent> getMotionEventsFromGestureDescription(
+        static List<GestureStep> getGestureStepsFromGestureDescription(
                 GestureDescription description, int sampleTimeMs) {
-            final List<MotionEvent> motionEvents = new ArrayList<>();
+            final List<GestureStep> gestureSteps = new ArrayList<>();
 
             // Point data at each time we generate an event for
             final TouchPoint[] currentTouchPoints =
                     getCurrentTouchPoints(description.getStrokeCount());
-            // Point data sent in last touch event
-            int lastTouchPointSize = 0;
-            final TouchPoint[] lastTouchPoints =
-                    getLastTouchPoints(description.getStrokeCount());
-
+            int currentTouchPointSize = 0;
             /* Loop through each time slice where there are touch points */
             long timeSinceGestureStart = 0;
             long nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart);
             while (nextKeyPointTime >= 0) {
-                timeSinceGestureStart = (lastTouchPointSize == 0) ? nextKeyPointTime
+                timeSinceGestureStart = (currentTouchPointSize == 0) ? nextKeyPointTime
                         : Math.min(nextKeyPointTime, timeSinceGestureStart + sampleTimeMs);
-                int currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart,
+                currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart,
                         currentTouchPoints);
-
-                appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
-                        currentTouchPoints, currentTouchPointSize, timeSinceGestureStart);
-                lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
-                        lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
-                        timeSinceGestureStart);
-                lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
-                        lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
-                        timeSinceGestureStart);
+                gestureSteps.add(new GestureStep(timeSinceGestureStart, currentTouchPointSize,
+                        currentTouchPoints));
 
                 /* Move to next time slice */
                 nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1);
             }
+            return gestureSteps;
+        }
+
+        public static List<MotionEvent> getMotionEventsFromGestureSteps(List<GestureStep> steps) {
+            final List<MotionEvent> motionEvents = new ArrayList<>();
+
+            // Number of points in last touch event
+            int lastTouchPointSize = 0;
+            TouchPoint[] lastTouchPoints;
+
+            for (int i = 0; i < steps.size(); i++) {
+                GestureStep step = steps.get(i);
+                int currentTouchPointSize = step.numTouchPoints;
+                lastTouchPoints = getLastTouchPoints(
+                        Math.max(lastTouchPointSize, currentTouchPointSize));
+
+                appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
+                        step.touchPoints, currentTouchPointSize, step.timeSinceGestureStart);
+                lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
+                        lastTouchPointSize, step.touchPoints, currentTouchPointSize,
+                        step.timeSinceGestureStart);
+                lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
+                        lastTouchPointSize, step.touchPoints, currentTouchPointSize,
+                        step.timeSinceGestureStart);
+            }
             return motionEvents;
         }
 
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 7a55079..81cddba 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -88,5 +88,5 @@
 
     void setSoftKeyboardCallbackEnabled(boolean enabled);
 
-    void sendMotionEvents(int sequence, in ParceledListSlice events);
+    void sendGesture(int sequence, in ParceledListSlice gestureSteps);
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a4c667f..5f8350f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -66,6 +66,7 @@
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.StrictMode;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -5591,7 +5592,11 @@
             return;
         }
 
-        mSearchManager = new SearchManager(this, null);
+        try {
+            mSearchManager = new SearchManager(this, null);
+        } catch (ServiceNotFoundException e) {
+            throw new IllegalStateException(e);
+        }
     }
 
     @Override
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index d6529d6..1367280 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1485,7 +1485,7 @@
      *
      * <p>If your app's <code>targetSdkVersion</code> is {@link android.os.Build.VERSION_CODES#M}
      * or lower, child fragments being restored from the savedInstanceState are restored after
-     * <code>onCreate</code> returns. When targeting @link android.os.Build.VERSION_CODES#N} or
+     * <code>onCreate</code> returns. When targeting {@link android.os.Build.VERSION_CODES#N} or
      * above and running on an N or newer platform version
      * they are restored by <code>Fragment.onCreate</code>.</p>
      *
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index db7d54b..ec22ff6 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -128,7 +128,7 @@
     /*
      * Backup: is the current system wallpaper image eligible for off-device backup?
      */
-    boolean isWallpaperBackupEligible(int userId);
+    boolean isWallpaperBackupEligible(int which, int userId);
 
     /*
      * Keyguard: register a callback for being notified that lock-state relevant
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 505e081..da99e80 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -27,6 +27,7 @@
 import android.os.IBinder;
 import android.os.IUserManager;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.view.IWindowManager;
@@ -192,12 +193,12 @@
     }
 
 
-    KeyguardManager() {
+    KeyguardManager() throws ServiceNotFoundException {
         mWM = WindowManagerGlobal.getWindowManagerService();
         mTrustManager = ITrustManager.Stub.asInterface(
-                ServiceManager.getService(Context.TRUST_SERVICE));
+                ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE));
         mUserManager = IUserManager.Stub.asInterface(
-                ServiceManager.getService(Context.USER_SERVICE));
+                ServiceManager.getServiceOrThrow(Context.USER_SERVICE));
     }
 
     /**
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index ac4abf5..ee6a3ac 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -31,6 +31,7 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
@@ -536,7 +537,7 @@
     /**
      * Reference to the shared system search service.
      */
-    private static ISearchManager mService;
+    private final ISearchManager mService;
 
     private final Context mContext;
 
@@ -547,11 +548,11 @@
 
     private SearchDialog mSearchDialog;
 
-    /*package*/ SearchManager(Context context, Handler handler)  {
+    /*package*/ SearchManager(Context context, Handler handler) throws ServiceNotFoundException {
         mContext = context;
         mHandler = handler;
         mService = ISearchManager.Stub.asInterface(
-                ServiceManager.getService(Context.SEARCH_SERVICE));
+                ServiceManager.getServiceOrThrow(Context.SEARCH_SERVICE));
     }
 
     /**
@@ -620,7 +621,7 @@
             return;
         }
 
-        UiModeManager uiModeManager = new UiModeManager();
+        final UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);
         // Don't show search dialog on televisions.
         if (uiModeManager.getCurrentModeType() != Configuration.UI_MODE_TYPE_TELEVISION) {
             ensureSearchDialog();
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 55744b9..1778ca7 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -16,14 +16,10 @@
 
 package android.app;
 
-import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.ISoundTriggerService;
-import com.android.internal.appwidget.IAppWidgetService;
-import com.android.internal.os.IDropBoxManagerService;
-
 import android.accounts.AccountManager;
 import android.accounts.IAccountManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.IDevicePolicyManager;
 import android.app.job.IJobScheduler;
 import android.app.job.JobScheduler;
 import android.app.trust.TrustManager;
@@ -36,7 +32,6 @@
 import android.content.Context;
 import android.content.IRestrictionsManager;
 import android.content.RestrictionsManager;
-import android.content.pm.ILauncherApps;
 import android.content.pm.IShortcutService;
 import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutManager;
@@ -48,13 +43,15 @@
 import android.hardware.SystemSensorManager;
 import android.hardware.camera2.CameraManager;
 import android.hardware.display.DisplayManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.IFingerprintService;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.IHdmiControlService;
 import android.hardware.input.InputManager;
 import android.hardware.location.ContextHubManager;
+import android.hardware.radio.RadioManager;
 import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbManager;
-import android.hardware.radio.RadioManager;
 import android.location.CountryDetector;
 import android.location.ICountryDetector;
 import android.location.ILocationManager;
@@ -90,8 +87,10 @@
 import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
 import android.os.BatteryManager;
+import android.os.BatteryStats;
 import android.os.DropBoxManager;
 import android.os.HardwarePropertiesManager;
+import android.os.IBatteryPropertiesRegistrar;
 import android.os.IBinder;
 import android.os.IHardwarePropertiesManager;
 import android.os.IPowerManager;
@@ -101,6 +100,7 @@
 import android.os.Process;
 import android.os.RecoverySystem;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemVibrator;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -109,8 +109,6 @@
 import android.os.storage.StorageManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.IFingerprintService;
 import android.service.persistentdata.IPersistentDataBlockService;
 import android.service.persistentdata.PersistentDataBlockManager;
 import android.telecom.TelecomManager;
@@ -120,7 +118,6 @@
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
-import com.android.internal.policy.PhoneLayoutInflater;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
@@ -128,6 +125,13 @@
 import android.view.inputmethod.InputMethodManager;
 import android.view.textservice.TextServicesManager;
 
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.app.ISoundTriggerService;
+import com.android.internal.appwidget.IAppWidgetService;
+import com.android.internal.os.IDropBoxManagerService;
+import com.android.internal.policy.PhoneLayoutInflater;
+
 import java.util.HashMap;
 
 /**
@@ -135,7 +139,7 @@
  * Used by {@link ContextImpl}.
  */
 final class SystemServiceRegistry {
-    private final static String TAG = "SystemServiceRegistry";
+    private static final String TAG = "SystemServiceRegistry";
 
     // Service registry information.
     // This information is never changed once static initialization has completed.
@@ -166,8 +170,8 @@
         registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
                 new CachedServiceFetcher<AccountManager>() {
             @Override
-            public AccountManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE);
+            public AccountManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.ACCOUNT_SERVICE);
                 IAccountManager service = IAccountManager.Stub.asInterface(b);
                 return new AccountManager(ctx, service);
             }});
@@ -182,8 +186,8 @@
         registerService(Context.ALARM_SERVICE, AlarmManager.class,
                 new CachedServiceFetcher<AlarmManager>() {
             @Override
-            public AlarmManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
+            public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);
                 IAlarmManager service = IAlarmManager.Stub.asInterface(b);
                 return new AlarmManager(service, ctx);
             }});
@@ -212,15 +216,15 @@
         registerService(Context.HDMI_CONTROL_SERVICE, HdmiControlManager.class,
                 new StaticServiceFetcher<HdmiControlManager>() {
             @Override
-            public HdmiControlManager createService() {
-                IBinder b = ServiceManager.getService(Context.HDMI_CONTROL_SERVICE);
+            public HdmiControlManager createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.HDMI_CONTROL_SERVICE);
                 return new HdmiControlManager(IHdmiControlService.Stub.asInterface(b));
             }});
 
         registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class,
                 new CachedServiceFetcher<ClipboardManager>() {
             @Override
-            public ClipboardManager createService(ContextImpl ctx) {
+            public ClipboardManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new ClipboardManager(ctx.getOuterContext(),
                         ctx.mMainThread.getHandler());
             }});
@@ -233,8 +237,8 @@
         registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
                 new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
             @Override
-            public ConnectivityManager createService(Context context) {
-                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+            public ConnectivityManager createService(Context context) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
                 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
                 return new ConnectivityManager(context, service);
             }});
@@ -242,16 +246,17 @@
         registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
                 new StaticServiceFetcher<CountryDetector>() {
             @Override
-            public CountryDetector createService() {
-                IBinder b = ServiceManager.getService(Context.COUNTRY_DETECTOR);
+            public CountryDetector createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.COUNTRY_DETECTOR);
                 return new CountryDetector(ICountryDetector.Stub.asInterface(b));
             }});
 
         registerService(Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class,
                 new CachedServiceFetcher<DevicePolicyManager>() {
             @Override
-            public DevicePolicyManager createService(ContextImpl ctx) {
-                return DevicePolicyManager.create(ctx);
+            public DevicePolicyManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.DEVICE_POLICY_SERVICE);
+                return new DevicePolicyManager(ctx, IDevicePolicyManager.Stub.asInterface(b));
             }});
 
         registerService(Context.DOWNLOAD_SERVICE, DownloadManager.class,
@@ -264,8 +269,12 @@
         registerService(Context.BATTERY_SERVICE, BatteryManager.class,
                 new StaticServiceFetcher<BatteryManager>() {
             @Override
-            public BatteryManager createService() {
-                return new BatteryManager();
+            public BatteryManager createService() throws ServiceNotFoundException {
+                IBatteryStats stats = IBatteryStats.Stub.asInterface(
+                        ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME));
+                IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub
+                        .asInterface(ServiceManager.getServiceOrThrow("batteryproperties"));
+                return new BatteryManager(stats, registrar);
             }});
 
         registerService(Context.NFC_SERVICE, NfcManager.class,
@@ -278,16 +287,9 @@
         registerService(Context.DROPBOX_SERVICE, DropBoxManager.class,
                 new CachedServiceFetcher<DropBoxManager>() {
             @Override
-            public DropBoxManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.DROPBOX_SERVICE);
+            public DropBoxManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.DROPBOX_SERVICE);
                 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
-                if (service == null) {
-                    // Don't return a DropBoxManager that will NPE upon use.
-                    // This also avoids caching a broken DropBoxManager in
-                    // getDropBoxManager during early boot, before the
-                    // DROPBOX_SERVICE is registered.
-                    return null;
-                }
                 return new DropBoxManager(ctx, service);
             }});
 
@@ -322,7 +324,7 @@
         registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class,
                 new StaticServiceFetcher<KeyguardManager>() {
             @Override
-            public KeyguardManager createService() {
+            public KeyguardManager createService() throws ServiceNotFoundException {
                 return new KeyguardManager();
             }});
 
@@ -336,17 +338,17 @@
         registerService(Context.LOCATION_SERVICE, LocationManager.class,
                 new CachedServiceFetcher<LocationManager>() {
             @Override
-            public LocationManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
+            public LocationManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE);
                 return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
             }});
 
         registerService(Context.NETWORK_POLICY_SERVICE, NetworkPolicyManager.class,
                 new CachedServiceFetcher<NetworkPolicyManager>() {
             @Override
-            public NetworkPolicyManager createService(ContextImpl ctx) {
+            public NetworkPolicyManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new NetworkPolicyManager(ctx, INetworkPolicyManager.Stub.asInterface(
-                        ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)));
+                        ServiceManager.getServiceOrThrow(Context.NETWORK_POLICY_SERVICE)));
             }});
 
         registerService(Context.NOTIFICATION_SERVICE, NotificationManager.class,
@@ -368,8 +370,8 @@
         registerService(Context.NSD_SERVICE, NsdManager.class,
                 new CachedServiceFetcher<NsdManager>() {
             @Override
-            public NsdManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.NSD_SERVICE);
+            public NsdManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.NSD_SERVICE);
                 INsdManager service = INsdManager.Stub.asInterface(b);
                 return new NsdManager(ctx.getOuterContext(), service);
             }});
@@ -377,12 +379,9 @@
         registerService(Context.POWER_SERVICE, PowerManager.class,
                 new CachedServiceFetcher<PowerManager>() {
             @Override
-            public PowerManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
+            public PowerManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
                 IPowerManager service = IPowerManager.Stub.asInterface(b);
-                if (service == null) {
-                    Log.wtf(TAG, "Failed to get power manager service.");
-                }
                 return new PowerManager(ctx.getOuterContext(),
                         service, ctx.mMainThread.getHandler());
             }});
@@ -390,19 +389,16 @@
         registerService(Context.RECOVERY_SERVICE, RecoverySystem.class,
                 new CachedServiceFetcher<RecoverySystem>() {
             @Override
-            public RecoverySystem createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.RECOVERY_SERVICE);
+            public RecoverySystem createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.RECOVERY_SERVICE);
                 IRecoverySystem service = IRecoverySystem.Stub.asInterface(b);
-                if (service == null) {
-                    Log.wtf(TAG, "Failed to get recovery service.");
-                }
                 return new RecoverySystem(service);
             }});
 
         registerService(Context.SEARCH_SERVICE, SearchManager.class,
                 new CachedServiceFetcher<SearchManager>() {
             @Override
-            public SearchManager createService(ContextImpl ctx) {
+            public SearchManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new SearchManager(ctx.getOuterContext(),
                         ctx.mMainThread.getHandler());
             }});
@@ -425,7 +421,7 @@
         registerService(Context.STORAGE_SERVICE, StorageManager.class,
                 new CachedServiceFetcher<StorageManager>() {
             @Override
-            public StorageManager createService(ContextImpl ctx) {
+            public StorageManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new StorageManager(ctx, ctx.mMainThread.getHandler().getLooper());
             }});
 
@@ -460,23 +456,23 @@
         registerService(Context.UI_MODE_SERVICE, UiModeManager.class,
                 new CachedServiceFetcher<UiModeManager>() {
             @Override
-            public UiModeManager createService(ContextImpl ctx) {
+            public UiModeManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new UiModeManager();
             }});
 
         registerService(Context.USB_SERVICE, UsbManager.class,
                 new CachedServiceFetcher<UsbManager>() {
             @Override
-            public UsbManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.USB_SERVICE);
+            public UsbManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.USB_SERVICE);
                 return new UsbManager(ctx, IUsbManager.Stub.asInterface(b));
             }});
 
         registerService(Context.SERIAL_SERVICE, SerialManager.class,
                 new CachedServiceFetcher<SerialManager>() {
             @Override
-            public SerialManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.SERIAL_SERVICE);
+            public SerialManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.SERIAL_SERVICE);
                 return new SerialManager(ctx, ISerialManager.Stub.asInterface(b));
             }});
 
@@ -498,8 +494,8 @@
         registerService(Context.WIFI_SERVICE, WifiManager.class,
                 new CachedServiceFetcher<WifiManager>() {
             @Override
-            public WifiManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);
+            public WifiManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SERVICE);
                 IWifiManager service = IWifiManager.Stub.asInterface(b);
                 return new WifiManager(ctx.getOuterContext(), service,
                         ConnectivityThread.getInstanceLooper());
@@ -508,8 +504,8 @@
         registerService(Context.WIFI_P2P_SERVICE, WifiP2pManager.class,
                 new StaticServiceFetcher<WifiP2pManager>() {
             @Override
-            public WifiP2pManager createService() {
-                IBinder b = ServiceManager.getService(Context.WIFI_P2P_SERVICE);
+            public WifiP2pManager createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_P2P_SERVICE);
                 IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b);
                 return new WifiP2pManager(service);
             }});
@@ -517,20 +513,17 @@
         registerService(Context.WIFI_NAN_SERVICE, WifiNanManager.class,
                 new StaticServiceFetcher<WifiNanManager>() {
             @Override
-            public WifiNanManager createService() {
-                IBinder b = ServiceManager.getService(Context.WIFI_NAN_SERVICE);
+            public WifiNanManager createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_NAN_SERVICE);
                 IWifiNanManager service = IWifiNanManager.Stub.asInterface(b);
-                if (service == null) {
-                    return null;
-                }
                 return new WifiNanManager(service);
             }});
 
         registerService(Context.WIFI_SCANNING_SERVICE, WifiScanner.class,
                 new CachedServiceFetcher<WifiScanner>() {
             @Override
-            public WifiScanner createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.WIFI_SCANNING_SERVICE);
+            public WifiScanner createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SCANNING_SERVICE);
                 IWifiScanner service = IWifiScanner.Stub.asInterface(b);
                 return new WifiScanner(ctx.getOuterContext(), service,
                         ConnectivityThread.getInstanceLooper());
@@ -539,8 +532,8 @@
         registerService(Context.WIFI_RTT_SERVICE, RttManager.class,
                 new CachedServiceFetcher<RttManager>() {
             @Override
-            public RttManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.WIFI_RTT_SERVICE);
+            public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT_SERVICE);
                 IRttManager service = IRttManager.Stub.asInterface(b);
                 return new RttManager(ctx.getOuterContext(), service,
                         ConnectivityThread.getInstanceLooper());
@@ -549,8 +542,8 @@
         registerService(Context.ETHERNET_SERVICE, EthernetManager.class,
                 new CachedServiceFetcher<EthernetManager>() {
             @Override
-            public EthernetManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.ETHERNET_SERVICE);
+            public EthernetManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.ETHERNET_SERVICE);
                 IEthernetManager service = IEthernetManager.Stub.asInterface(b);
                 return new EthernetManager(ctx.getOuterContext(), service);
             }});
@@ -565,8 +558,8 @@
         registerService(Context.USER_SERVICE, UserManager.class,
                 new CachedServiceFetcher<UserManager>() {
             @Override
-            public UserManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.USER_SERVICE);
+            public UserManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.USER_SERVICE);
                 IUserManager service = IUserManager.Stub.asInterface(b);
                 return new UserManager(ctx, service);
             }});
@@ -574,8 +567,8 @@
         registerService(Context.APP_OPS_SERVICE, AppOpsManager.class,
                 new CachedServiceFetcher<AppOpsManager>() {
             @Override
-            public AppOpsManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
+            public AppOpsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.APP_OPS_SERVICE);
                 IAppOpsService service = IAppOpsService.Stub.asInterface(b);
                 return new AppOpsManager(ctx, service);
             }});
@@ -597,8 +590,8 @@
         registerService(Context.RESTRICTIONS_SERVICE, RestrictionsManager.class,
                 new CachedServiceFetcher<RestrictionsManager>() {
             @Override
-            public RestrictionsManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.RESTRICTIONS_SERVICE);
+            public RestrictionsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.RESTRICTIONS_SERVICE);
                 IRestrictionsManager service = IRestrictionsManager.Stub.asInterface(b);
                 return new RestrictionsManager(ctx, service);
             }});
@@ -606,8 +599,8 @@
         registerService(Context.PRINT_SERVICE, PrintManager.class,
                 new CachedServiceFetcher<PrintManager>() {
             @Override
-            public PrintManager createService(ContextImpl ctx) {
-                IBinder iBinder = ServiceManager.getService(Context.PRINT_SERVICE);
+            public PrintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder iBinder = ServiceManager.getServiceOrThrow(Context.PRINT_SERVICE);
                 IPrintManager service = IPrintManager.Stub.asInterface(iBinder);
                 return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(),
                         UserHandle.getAppId(Process.myUid()));
@@ -616,7 +609,7 @@
         registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
                 new CachedServiceFetcher<ConsumerIrManager>() {
             @Override
-            public ConsumerIrManager createService(ContextImpl ctx) {
+            public ConsumerIrManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new ConsumerIrManager(ctx);
             }});
 
@@ -630,16 +623,16 @@
         registerService(Context.TRUST_SERVICE, TrustManager.class,
                 new StaticServiceFetcher<TrustManager>() {
             @Override
-            public TrustManager createService() {
-                IBinder b = ServiceManager.getService(Context.TRUST_SERVICE);
+            public TrustManager createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE);
                 return new TrustManager(b);
             }});
 
         registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class,
                 new CachedServiceFetcher<FingerprintManager>() {
             @Override
-            public FingerprintManager createService(ContextImpl ctx) {
-                IBinder binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE);
+            public FingerprintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder binder = ServiceManager.getServiceOrThrow(Context.FINGERPRINT_SERVICE);
                 IFingerprintService service = IFingerprintService.Stub.asInterface(binder);
                 return new FingerprintManager(ctx.getOuterContext(), service);
             }});
@@ -647,8 +640,8 @@
         registerService(Context.TV_INPUT_SERVICE, TvInputManager.class,
                 new StaticServiceFetcher<TvInputManager>() {
             @Override
-            public TvInputManager createService() {
-                IBinder iBinder = ServiceManager.getService(Context.TV_INPUT_SERVICE);
+            public TvInputManager createService() throws ServiceNotFoundException {
+                IBinder iBinder = ServiceManager.getServiceOrThrow(Context.TV_INPUT_SERVICE);
                 ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder);
                 return new TvInputManager(service, UserHandle.myUserId());
             }});
@@ -656,15 +649,15 @@
         registerService(Context.NETWORK_SCORE_SERVICE, NetworkScoreManager.class,
                 new CachedServiceFetcher<NetworkScoreManager>() {
             @Override
-            public NetworkScoreManager createService(ContextImpl ctx) {
+            public NetworkScoreManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new NetworkScoreManager(ctx);
             }});
 
         registerService(Context.USAGE_STATS_SERVICE, UsageStatsManager.class,
                 new CachedServiceFetcher<UsageStatsManager>() {
             @Override
-            public UsageStatsManager createService(ContextImpl ctx) {
-                IBinder iBinder = ServiceManager.getService(Context.USAGE_STATS_SERVICE);
+            public UsageStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder iBinder = ServiceManager.getServiceOrThrow(Context.USAGE_STATS_SERVICE);
                 IUsageStatsManager service = IUsageStatsManager.Stub.asInterface(iBinder);
                 return new UsageStatsManager(ctx.getOuterContext(), service);
             }});
@@ -672,23 +665,23 @@
         registerService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class,
                 new CachedServiceFetcher<NetworkStatsManager>() {
             @Override
-            public NetworkStatsManager createService(ContextImpl ctx) {
+            public NetworkStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new NetworkStatsManager(ctx.getOuterContext());
             }});
 
         registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
                 new StaticServiceFetcher<JobScheduler>() {
             @Override
-            public JobScheduler createService() {
-                IBinder b = ServiceManager.getService(Context.JOB_SCHEDULER_SERVICE);
+            public JobScheduler createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.JOB_SCHEDULER_SERVICE);
                 return new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b));
             }});
 
         registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class,
                 new StaticServiceFetcher<PersistentDataBlockManager>() {
             @Override
-            public PersistentDataBlockManager createService() {
-                IBinder b = ServiceManager.getService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+            public PersistentDataBlockManager createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.PERSISTENT_DATA_BLOCK_SERVICE);
                 IPersistentDataBlockService persistentDataBlockService =
                         IPersistentDataBlockService.Stub.asInterface(b);
                 if (persistentDataBlockService != null) {
@@ -709,19 +702,16 @@
         registerService(Context.APPWIDGET_SERVICE, AppWidgetManager.class,
                 new CachedServiceFetcher<AppWidgetManager>() {
             @Override
-            public AppWidgetManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
+            public AppWidgetManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.APPWIDGET_SERVICE);
                 return new AppWidgetManager(ctx, IAppWidgetService.Stub.asInterface(b));
             }});
 
         registerService(Context.MIDI_SERVICE, MidiManager.class,
                 new CachedServiceFetcher<MidiManager>() {
             @Override
-            public MidiManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.MIDI_SERVICE);
-                if (b == null) {
-                    return null;
-                }
+            public MidiManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.MIDI_SERVICE);
                 return new MidiManager(IMidiManager.Stub.asInterface(b));
             }});
 
@@ -735,43 +725,41 @@
         registerService(Context.HARDWARE_PROPERTIES_SERVICE, HardwarePropertiesManager.class,
                 new CachedServiceFetcher<HardwarePropertiesManager>() {
             @Override
-            public HardwarePropertiesManager createService(ContextImpl ctx) {
-                    IBinder b = ServiceManager.getService(Context.HARDWARE_PROPERTIES_SERVICE);
-                    IHardwarePropertiesManager service =
-                            IHardwarePropertiesManager.Stub.asInterface(b);
-                    if (service == null) {
-                        Log.wtf(TAG, "Failed to get hardwareproperties service.");
-                        return null;
-                    }
-                    return new HardwarePropertiesManager(ctx, service);
+            public HardwarePropertiesManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.HARDWARE_PROPERTIES_SERVICE);
+                IHardwarePropertiesManager service =
+                        IHardwarePropertiesManager.Stub.asInterface(b);
+                return new HardwarePropertiesManager(ctx, service);
             }});
 
         registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class,
                 new CachedServiceFetcher<SoundTriggerManager>() {
             @Override
-            public SoundTriggerManager createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE);
+            public SoundTriggerManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.SOUND_TRIGGER_SERVICE);
                 return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b));
             }});
 
         registerService(Context.SHORTCUT_SERVICE, ShortcutManager.class,
                 new CachedServiceFetcher<ShortcutManager>() {
             @Override
-            public ShortcutManager createService(ContextImpl ctx) {
-                return new ShortcutManager(ctx);
+            public ShortcutManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.SHORTCUT_SERVICE);
+                return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b));
             }});
 
         registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class,
                 new CachedServiceFetcher<SystemHealthManager>() {
             @Override
-            public SystemHealthManager createService(ContextImpl ctx) {
-                return new SystemHealthManager();
+            public SystemHealthManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME);
+                return new SystemHealthManager(IBatteryStats.Stub.asInterface(b));
             }});
 
         registerService(Context.CONTEXTHUB_SERVICE, ContextHubManager.class,
                 new CachedServiceFetcher<ContextHubManager>() {
             @Override
-            public ContextHubManager createService(ContextImpl ctx) {
+            public ContextHubManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 return new ContextHubManager(ctx.getOuterContext(),
                   ctx.mMainThread.getHandler().getLooper());
             }});
@@ -836,14 +824,18 @@
                 // Fetch or create the service.
                 Object service = cache[mCacheIndex];
                 if (service == null) {
-                    service = createService(ctx);
-                    cache[mCacheIndex] = service;
+                    try {
+                        service = createService(ctx);
+                        cache[mCacheIndex] = service;
+                    } catch (ServiceNotFoundException e) {
+                        Log.w(TAG, e.getMessage(), e);
+                    }
                 }
                 return (T)service;
             }
         }
 
-        public abstract T createService(ContextImpl ctx);
+        public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
     }
 
     /**
@@ -857,13 +849,17 @@
         public final T getService(ContextImpl unused) {
             synchronized (StaticServiceFetcher.this) {
                 if (mCachedInstance == null) {
-                    mCachedInstance = createService();
+                    try {
+                        mCachedInstance = createService();
+                    } catch (ServiceNotFoundException e) {
+                        Log.w(TAG, e.getMessage(), e);
+                    }
                 }
                 return mCachedInstance;
             }
         }
 
-        public abstract T createService();
+        public abstract T createService() throws ServiceNotFoundException;
     }
 
     /**
@@ -886,13 +882,16 @@
                     // it's the application context very early in app initialization. In both these
                     // cases, the passed-in ContextImpl will not be freed, so it's safe to pass it
                     // to the service. http://b/27532714 .
-                    mCachedInstance = createService(appContext != null ? appContext : ctx);
+                    try {
+                        mCachedInstance = createService(appContext != null ? appContext : ctx);
+                    } catch (ServiceNotFoundException e) {
+                        Log.w(TAG, e.getMessage(), e);
+                    }
                 }
                 return mCachedInstance;
             }
         }
 
-        public abstract T createService(Context applicationContext);
+        public abstract T createService(Context applicationContext) throws ServiceNotFoundException;
     }
-
 }
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 69e8df8..0046b0e 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -22,6 +22,7 @@
 import android.content.res.Configuration;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.Log;
 
 import java.lang.annotation.Retention;
@@ -123,9 +124,9 @@
 
     private IUiModeManager mService;
 
-    /*package*/ UiModeManager() {
+    /*package*/ UiModeManager() throws ServiceNotFoundException {
         mService = IUiModeManager.Stub.asInterface(
-                ServiceManager.getService(Context.UI_MODE_SERVICE));
+                ServiceManager.getServiceOrThrow(Context.UI_MODE_SERVICE));
     }
 
     /**
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 20cbde1..6e44662 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1680,13 +1680,13 @@
      * Only the OS itself may use this method.
      * @hide
      */
-    public boolean isWallpaperBackupEligible() {
+    public boolean isWallpaperBackupEligible(int which) {
         if (sGlobals.mService == null) {
             Log.w(TAG, "WallpaperService not running");
             throw new RuntimeException(new DeadSystemException());
         }
         try {
-            return sGlobals.mService.isWallpaperBackupEligible(mContext.getUserId());
+            return sGlobals.mService.isWallpaperBackupEligible(which, mContext.getUserId());
         } catch (RemoteException e) {
             Log.e(TAG, "Exception querying wallpaper backup eligibility: " + e.getMessage());
         }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3a2038f..6ac7132 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -46,6 +46,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.provider.ContactsContract.Directory;
 import android.provider.Settings;
 import android.security.Credentials;
@@ -99,28 +100,20 @@
     private final IDevicePolicyManager mService;
     private final boolean mParentInstance;
 
-    private DevicePolicyManager(Context context, boolean parentInstance) {
-        this(context,
-                IDevicePolicyManager.Stub.asInterface(
-                        ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)),
-                parentInstance);
+    /** @hide */
+    public DevicePolicyManager(Context context, IDevicePolicyManager service) {
+        this(context, service, false);
     }
 
     /** @hide */
     @VisibleForTesting
-    protected DevicePolicyManager(
-            Context context, IDevicePolicyManager service, boolean parentInstance) {
+    protected DevicePolicyManager(Context context, IDevicePolicyManager service,
+            boolean parentInstance) {
         mContext = context;
         mService = service;
         mParentInstance = parentInstance;
     }
 
-    /** @hide */
-    public static DevicePolicyManager create(Context context) {
-        DevicePolicyManager me = new DevicePolicyManager(context, false);
-        return me.mService != null ? me : null;
-    }
-
     /** @hide test will override it. */
     @VisibleForTesting
     protected int myUserId() {
@@ -6054,7 +6047,7 @@
             if (!mService.isManagedProfile(admin)) {
                 throw new SecurityException("The current user does not have a parent profile.");
             }
-            return new DevicePolicyManager(mContext, true);
+            return new DevicePolicyManager(mContext, mService, true);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -6146,7 +6139,7 @@
             throw new SecurityException("The user " + uInfo.id
                     + " does not have a parent profile.");
         }
-        return new DevicePolicyManager(mContext, true);
+        return new DevicePolicyManager(mContext, mService, true);
     }
 
     /**
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 7961a72..e805fab 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -34,6 +34,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.Log;
 
 /**
@@ -95,10 +96,10 @@
     /**
      * {@hide}
      */
-    public NetworkStatsManager(Context context) {
+    public NetworkStatsManager(Context context) throws ServiceNotFoundException {
         mContext = context;
         mService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+                ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
     }
 
     /**
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 8e659e0..f53ca94 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -31,6 +31,8 @@
  */
 public class OobData implements Parcelable {
     private byte[] securityManagerTk;
+    private byte[] leSecureConnectionsConfirmation;
+    private byte[] leSecureConnectionsRandom;
 
     public byte[] getSecurityManagerTk() {
         return securityManagerTk;
@@ -45,10 +47,28 @@
         this.securityManagerTk = securityManagerTk;
     }
 
+    public byte[] getLeSecureConnectionsConfirmation() {
+        return leSecureConnectionsConfirmation;
+    }
+
+    public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) {
+        this.leSecureConnectionsConfirmation = leSecureConnectionsConfirmation;
+    }
+
+    public byte[] getLeSecureConnectionsRandom() {
+        return leSecureConnectionsRandom;
+    }
+
+    public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) {
+        this.leSecureConnectionsRandom = leSecureConnectionsRandom;
+    }
+
     public OobData() { }
 
     private OobData(Parcel in) {
         securityManagerTk = in.createByteArray();
+        leSecureConnectionsConfirmation = in.createByteArray();
+        leSecureConnectionsRandom = in.createByteArray();
     }
 
     public int describeContents() {
@@ -58,6 +78,8 @@
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeByteArray(securityManagerTk);
+        out.writeByteArray(leSecureConnectionsConfirmation);
+        out.writeByteArray(leSecureConnectionsRandom);
     }
 
     public static final Parcelable.Creator<OobData> CREATOR
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 7244227..c28172c 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -16,12 +16,11 @@
 
 package android.content;
 
-import android.content.Context;
+import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 
 import java.util.ArrayList;
 
@@ -49,10 +48,8 @@
  * @see android.content.Context#getSystemService
  */
 public class ClipboardManager extends android.text.ClipboardManager {
-    private final static Object sStaticLock = new Object();
-    private static IClipboard sService;
-
     private final Context mContext;
+    private final IClipboard mService;
 
     private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners
              = new ArrayList<OnPrimaryClipChangedListener>();
@@ -93,20 +90,11 @@
         void onPrimaryClipChanged();
     }
 
-    static private IClipboard getService() {
-        synchronized (sStaticLock) {
-            if (sService != null) {
-                return sService;
-            }
-            IBinder b = ServiceManager.getService("clipboard");
-            sService = IClipboard.Stub.asInterface(b);
-            return sService;
-        }
-    }
-
     /** {@hide} */
-    public ClipboardManager(Context context, Handler handler) {
+    public ClipboardManager(Context context, Handler handler) throws ServiceNotFoundException {
         mContext = context;
+        mService = IClipboard.Stub.asInterface(
+                ServiceManager.getServiceOrThrow(Context.CLIPBOARD_SERVICE));
     }
 
     /**
@@ -120,7 +108,7 @@
             if (clip != null) {
                 clip.prepareToLeaveProcess(true);
             }
-            getService().setPrimaryClip(clip, mContext.getOpPackageName());
+            mService.setPrimaryClip(clip, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -131,7 +119,7 @@
      */
     public ClipData getPrimaryClip() {
         try {
-            return getService().getPrimaryClip(mContext.getOpPackageName());
+            return mService.getPrimaryClip(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -143,7 +131,7 @@
      */
     public ClipDescription getPrimaryClipDescription() {
         try {
-            return getService().getPrimaryClipDescription(mContext.getOpPackageName());
+            return mService.getPrimaryClipDescription(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -154,7 +142,7 @@
      */
     public boolean hasPrimaryClip() {
         try {
-            return getService().hasPrimaryClip(mContext.getOpPackageName());
+            return mService.hasPrimaryClip(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -164,7 +152,7 @@
         synchronized (mPrimaryClipChangedListeners) {
             if (mPrimaryClipChangedListeners.size() == 0) {
                 try {
-                    getService().addPrimaryClipChangedListener(
+                    mService.addPrimaryClipChangedListener(
                             mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
@@ -179,7 +167,7 @@
             mPrimaryClipChangedListeners.remove(what);
             if (mPrimaryClipChangedListeners.size() == 0) {
                 try {
-                    getService().removePrimaryClipChangedListener(
+                    mService.removePrimaryClipChangedListener(
                             mPrimaryClipChangedServiceListener);
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
@@ -217,7 +205,7 @@
     @Deprecated
     public boolean hasText() {
         try {
-            return getService().hasClipboardText(mContext.getOpPackageName());
+            return mService.hasClipboardText(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java
index 953b051..f47ad1f 100644
--- a/core/java/android/content/pm/IntentFilterVerificationInfo.java
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java
@@ -60,9 +60,9 @@
         mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
     }
 
-    public IntentFilterVerificationInfo(String packageName, ArrayList<String> domains) {
+    public IntentFilterVerificationInfo(String packageName, ArraySet<String> domains) {
         mPackageName = packageName;
-        mDomains.addAll(domains);
+        mDomains = domains;
         mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
     }
 
@@ -96,8 +96,8 @@
         return mDomains;
     }
 
-    public void setDomains(ArrayList<String> list) {
-        mDomains = new ArraySet<>(list);
+    public void setDomains(ArraySet<String> list) {
+        mDomains = list;
     }
 
     public String getDomainsString() {
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index 9fa1c3f..b221e16 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.Log;
 
 /**
@@ -40,10 +41,10 @@
     /**
      * @hide to prevent subclassing from outside of the framework
      */
-    public ConsumerIrManager(Context context) {
+    public ConsumerIrManager(Context context) throws ServiceNotFoundException {
         mPackageName = context.getPackageName();
         mService = IConsumerIrService.Stub.asInterface(
-                ServiceManager.getService(Context.CONSUMER_IR_SERVICE));
+                ServiceManager.getServiceOrThrow(Context.CONSUMER_IR_SERVICE));
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index c23bd5b..b10c341 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -286,23 +286,29 @@
     }
 
     @Override
-    public synchronized void abortCaptures() throws CameraAccessException {
-        checkNotClosed();
+    public void abortCaptures() throws CameraAccessException {
+        synchronized (this) {
+            checkNotClosed();
 
-        if (DEBUG) {
-            Log.v(TAG, mIdString + "abortCaptures");
+            if (DEBUG) {
+                Log.v(TAG, mIdString + "abortCaptures");
+            }
+
+            if (mAborting) {
+                Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing");
+                return;
+            }
+
+            mAborting = true;
+            mAbortDrainer.taskStarted();
         }
 
-        if (mAborting) {
-            Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing");
-            return;
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            synchronized (this) {
+                mDeviceImpl.flush();
+                // The next BUSY -> IDLE set of transitions will mark the end of the abort.
+            }
         }
-
-        mAborting = true;
-        mAbortDrainer.taskStarted();
-
-        mDeviceImpl.flush();
-        // The next BUSY -> IDLE set of transitions will mark the end of the abort.
     }
 
     @Override
@@ -330,78 +336,86 @@
      * @see CameraCaptureSession#close
      */
     @Override
-    public synchronized void replaceSessionClose() {
-        /*
-         * In order for creating new sessions to be fast, the new session should be created
-         * before the old session is closed.
-         *
-         * Otherwise the old session will always unconfigure if there is no new session to
-         * replace it.
-         *
-         * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt
-         * to skip unconfigure if a new session is created before the captures are all drained,
-         * but this would introduce nondeterministic behavior.
-         */
+    public void replaceSessionClose() {
+        synchronized (this) {
+            /*
+             * In order for creating new sessions to be fast, the new session should be created
+             * before the old session is closed.
+             *
+             * Otherwise the old session will always unconfigure if there is no new session to
+             * replace it.
+             *
+             * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt
+             * to skip unconfigure if a new session is created before the captures are all drained,
+             * but this would introduce nondeterministic behavior.
+             */
 
-        if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose");
+            if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose");
 
-        // Set up fast shutdown. Possible alternative paths:
-        // - This session is active, so close() below starts the shutdown drain
-        // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener.
-        // - This session is already closed and has executed the idle drain listener, and
-        //   configureOutputsChecked(null) has already been called.
-        //
-        // Do not call configureOutputsChecked(null) going forward, since it would race with the
-        // configuration for the new session. If it was already called, then we don't care, since it
-        // won't get called again.
-        mSkipUnconfigure = true;
-
+            // Set up fast shutdown. Possible alternative paths:
+            // - This session is active, so close() below starts the shutdown drain
+            // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener.
+            // - This session is already closed and has executed the idle drain listener, and
+            //   configureOutputsChecked(null) has already been called.
+            //
+            // Do not call configureOutputsChecked(null) going forward, since it would race with the
+            // configuration for the new session. If it was already called, then we don't care,
+            // since it won't get called again.
+            mSkipUnconfigure = true;
+        }
         close();
     }
 
     @Override
-    public synchronized void close() {
+    public void close() {
+        synchronized (this) {
+            if (mClosed) {
+                if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
+                return;
+            }
 
-        if (mClosed) {
-            if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
-            return;
+            if (DEBUG) Log.v(TAG, mIdString + "close - first time");
+
+            mClosed = true;
         }
 
-        if (DEBUG) Log.v(TAG, mIdString + "close - first time");
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            synchronized (this) {
+                /*
+                 * Flush out any repeating request. Since camera is closed, no new requests
+                 * can be queued, and eventually the entire request queue will be drained.
+                 *
+                 * If the camera device was already closed, short circuit and do nothing; since
+                 * no more internal device callbacks will fire anyway.
+                 *
+                 * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure
+                 * the camera. Once that's done, fire #onClosed.
+                 */
+                try {
+                    mDeviceImpl.stopRepeating();
+                } catch (IllegalStateException e) {
+                    // OK: Camera device may already be closed, nothing else to do
 
-        mClosed = true;
+                    // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
+                    // or just suppress the ISE only and rely onClosed.
+                    // Also skip any of the draining work if this is already closed.
 
-        /*
-         * Flush out any repeating request. Since camera is closed, no new requests
-         * can be queued, and eventually the entire request queue will be drained.
-         *
-         * If the camera device was already closed, short circuit and do nothing; since
-         * no more internal device callbacks will fire anyway.
-         *
-         * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure the
-         * camera. Once that's done, fire #onClosed.
-         */
-        try {
-            mDeviceImpl.stopRepeating();
-        } catch (IllegalStateException e) {
-            // OK: Camera device may already be closed, nothing else to do
+                    // Short-circuit; queue callback immediately and return
+                    mStateCallback.onClosed(this);
+                    return;
+                } catch (CameraAccessException e) {
+                    // OK: close does not throw checked exceptions.
+                    Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);
 
-            // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
-            // or just suppress the ISE only and rely onClosed.
-            // Also skip any of the draining work if this is already closed.
-
-            // Short-circuit; queue callback immediately and return
-            mStateCallback.onClosed(this);
-            return;
-        } catch (CameraAccessException e) {
-            // OK: close does not throw checked exceptions.
-            Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);
-
-            // TODO: call onError instead of onClosed if this happens
+                    // TODO: call onError instead of onClosed if this happens
+                }
+            }
         }
 
-        // If no sequences are pending, fire #onClosed immediately
-        mSequenceDrainer.beginDrain();
+        synchronized (this) {
+            // If no sequences are pending, fire #onClosed immediately
+            mSequenceDrainer.beginDrain();
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 803337b..2b0593f 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -33,6 +33,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.Vibrator;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
@@ -225,8 +226,12 @@
     public static InputManager getInstance() {
         synchronized (InputManager.class) {
             if (sInstance == null) {
-                IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
-                sInstance = new InputManager(IInputManager.Stub.asInterface(b));
+                try {
+                    sInstance = new InputManager(IInputManager.Stub
+                            .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
+                } catch (ServiceNotFoundException e) {
+                    throw new IllegalStateException(e);
+                }
             }
             return sInstance;
         }
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 3bc1562..2aed53c 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -18,10 +18,10 @@
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.Log;
 
 /**
@@ -38,7 +38,7 @@
     private static final String TAG = "ContextHubManager";
 
     private final Looper mMainLooper;
-    private IContextHubService mContextHubService;
+    private final IContextHubService mService;
     private Callback mCallback;
     private Handler mCallbackHandler;
 
@@ -92,13 +92,11 @@
      * @return array of context hub handles
      */
     public int[] getContextHubHandles() {
-        int[] retVal = null;
         try {
-            retVal = getBinder().getContextHubHandles();
+            return mService.getContextHubHandles();
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not fetch context hub handles : " + e);
+            throw e.rethrowFromSystemServer();
         }
-        return retVal;
     }
 
     /**
@@ -110,14 +108,11 @@
      * @see ContextHubInfo
      */
     public ContextHubInfo getContextHubInfo(int hubHandle) {
-        ContextHubInfo retVal = null;
         try {
-            retVal = getBinder().getContextHubInfo(hubHandle);
+            return mService.getContextHubInfo(hubHandle);
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not fetch context hub info :" + e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return retVal;
     }
 
     /**
@@ -132,19 +127,11 @@
      * @see NanoApp
      */
     public int loadNanoApp(int hubHandle, NanoApp app) {
-        int retVal = -1;
-
-        if (app == null) {
-            return retVal;
-        }
-
         try {
-            retVal = getBinder().loadNanoApp(hubHandle, app);
+            return mService.loadNanoApp(hubHandle, app);
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not load nanoApp :" + e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return retVal;
     }
 
     /**
@@ -155,15 +142,11 @@
      * @return int  0 on success, -1 otherwise
      */
     public int unloadNanoApp(int nanoAppHandle) {
-        int retVal = -1;
-
         try {
-            retVal = getBinder().unloadNanoApp(nanoAppHandle);
+            return mService.unloadNanoApp(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not fetch unload nanoApp :" + e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return retVal;
     }
 
     /**
@@ -175,15 +158,11 @@
      * @see NanoAppInstanceInfo
      */
     public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
-        NanoAppInstanceInfo retVal = null;
-
         try {
-            retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
+            return mService.getNanoAppInstanceInfo(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not fetch nanoApp info :" + e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return retVal;
     }
 
     /**
@@ -197,13 +176,11 @@
      * @return int[] Array of handles to any found nano apps
      */
     public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
-        int[] retVal = null;
         try {
-            retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
+            return mService.findNanoAppOnHub(hubHandle, filter);
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not query nanoApp instance :" + e);
+            throw e.rethrowFromSystemServer();
         }
-        return retVal;
     }
 
     /**
@@ -218,19 +195,11 @@
      * @return int 0 on success, -1 otherwise
      */
     public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
-        int retVal = -1;
-
-        if (message == null || message.getData() == null) {
-            Log.w(TAG, "null ptr");
-            return retVal;
-        }
         try {
-            retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message);
+            return mService.sendMessage(hubHandle, nanoAppHandle, message);
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not send message :" + e.toString());
+            throw e.rethrowFromSystemServer();
         }
-
-        return retVal;
     }
 
     /**
@@ -318,7 +287,7 @@
         return 0;
     }
 
-    private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
+    private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
         @Override
         public void onMessageReceipt(final int hubId, final int nanoAppId,
                 final ContextHubMessage message) {
@@ -346,29 +315,17 @@
         }
     };
 
-    /** @hide */
-    public ContextHubManager(Context context, Looper mainLooper) {
+    /** @throws ServiceNotFoundException
+     * @hide */
+    public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException {
         mMainLooper = mainLooper;
+        mService = IContextHubService.Stub.asInterface(
+                ServiceManager.getServiceOrThrow(ContextHubService.CONTEXTHUB_SERVICE));
 
-        IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
-        if (b != null) {
-            mContextHubService = IContextHubService.Stub.asInterface(b);
-
-            try {
-                getBinder().registerCallback(mClientCallback);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Could not register callback:" + e);
-            }
-
-        } else {
-            Log.w(TAG, "failed to getService");
+        try {
+            mService.registerCallback(mClientCallback);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Could not register callback:" + e);
         }
     }
-
-    private IContextHubService getBinder() throws RemoteException {
-        if (mContextHubService == null) {
-            throw new RemoteException("Service not connected.");
-        }
-        return mContextHubService;
-    }
 }
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 062c958..893ed3f 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -154,6 +154,9 @@
             Log.e(TAG, "Invalid contextHubhandle " + contextHubHandle);
             return -1;
         }
+        if (app == null) {
+            return -1;
+        }
 
         int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE];
         msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle;
@@ -240,6 +243,11 @@
                            throws RemoteException {
         checkPermissions();
 
+        if (msg == null || msg.getData() == null) {
+            Log.w(TAG, "null ptr");
+            return -1;
+        }
+
         int[] msgHeader = new int[MSG_HEADER_SIZE];
         msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
         msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle;
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 01c160f..c2286ad 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -23,9 +23,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.NetworkScorerAppManager.NetworkScorerAppData;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.UserHandle;
 
 /**
@@ -127,10 +127,10 @@
     private final INetworkScoreService mService;
 
     /** @hide */
-    public NetworkScoreManager(Context context) {
+    public NetworkScoreManager(Context context) throws ServiceNotFoundException {
         mContext = context;
-        IBinder iBinder = ServiceManager.getService(Context.NETWORK_SCORE_SERVICE);
-        mService = INetworkScoreService.Stub.asInterface(iBinder);
+        mService = INetworkScoreService.Stub
+                .asInterface(ServiceManager.getServiceOrThrow(Context.NETWORK_SCORE_SERVICE));
     }
 
     /**
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index d39968a..252385f 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,11 +16,6 @@
 
 package android.os;
 
-import android.content.Context;
-import android.os.BatteryProperty;
-import android.os.IBatteryPropertiesRegistrar;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import com.android.internal.app.IBatteryStats;
 
 /**
@@ -218,6 +213,13 @@
                 ServiceManager.getService("batteryproperties"));
     }
 
+    /** {@hide} */
+    public BatteryManager(IBatteryStats batteryStats,
+            IBatteryPropertiesRegistrar batteryPropertiesRegistrar) {
+        mBatteryStats = batteryStats;
+        mBatteryPropertiesRegistrar = batteryPropertiesRegistrar;
+    }
+
     /**
      * Return true if the battery is currently considered to be charging.  This means that
      * the device is plugged in and is supplying sufficient power that the battery level is
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 68aaa1f..91fe352 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -677,9 +677,9 @@
          * <li> {@link android.app.DownloadManager.Request#setAllowedNetworkTypes
          * DownloadManager.Request.setAllowedNetworkTypes}
          * will disable "allow over metered" when specifying only
-         * {@link android.app.DownloadManager.Request#NETWORK_WIFI}.
+         * {@link android.app.DownloadManager.Request#NETWORK_WIFI}.</li>
          * <li> {@link android.app.DownloadManager} no longer allows access to raw
-         * file paths.
+         * file paths.</li>
          * <li> {@link android.app.Notification.Builder#setShowWhen
          * Notification.Builder.setShowWhen}
          * must be called explicitly to have the time shown, and various other changes in
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 2ba4aa4..640105c 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -16,10 +16,10 @@
 
 package android.os;
 
-import com.android.internal.os.BinderInternal;
-
 import android.util.Log;
 
+import com.android.internal.os.BinderInternal;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -61,6 +61,21 @@
     }
 
     /**
+     * Returns a reference to a service with the given name, or throws
+     * {@link NullPointerException} if none is found.
+     *
+     * @hide
+     */
+    public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
+        final IBinder binder = getService(name);
+        if (binder != null) {
+            return binder;
+        } else {
+            throw new ServiceNotFoundException(name);
+        }
+    }
+
+    /**
      * Place a new @a service called @a name into the service
      * manager.
      * 
@@ -138,4 +153,17 @@
         }
         sCache.putAll(cache);
     }
+
+    /**
+     * Exception thrown when no service published for given name. This might be
+     * thrown early during boot before certain services have published
+     * themselves.
+     *
+     * @hide
+     */
+    public static class ServiceNotFoundException extends Exception {
+        public ServiceNotFoundException(String name) {
+            super("No service published for: " + name);
+        }
+    }
 }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index cfd016e..06e2931 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -615,7 +615,8 @@
 
     /**
      * Specifies if a user is not allowed to enable the oem unlock setting. The default value is
-     * <code>false</code>.
+     * <code>false</code>. Setting this restriction has no effect if the bootloader is already
+     * unlocked.
      *
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 32e8425..7c0af25 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -21,6 +21,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 
 import com.android.internal.app.IBatteryStats;
 
@@ -47,8 +48,12 @@
      * @hide
      */
     public SystemHealthManager() {
-        mBatteryStats = IBatteryStats.Stub.asInterface(
-            ServiceManager.getService(BatteryStats.SERVICE_NAME));
+        this(IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME)));
+    }
+
+    /** {@hide} */
+    public SystemHealthManager(IBatteryStats batteryStats) {
+        mBatteryStats = batteryStats;
     }
 
     /**
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index c5507b9..cee7553 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -35,6 +35,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -341,7 +342,7 @@
      * Constructs a StorageManager object through which an application can
      * can communicate with the systems mount service.
      *
-     * @param tgtLooper The {@link android.os.Looper} which events will be received on.
+     * @param looper The {@link android.os.Looper} which events will be received on.
      *
      * <p>Applications can get instance of this class by calling
      * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
@@ -349,14 +350,11 @@
      *
      * @hide
      */
-    public StorageManager(Context context, Looper looper) {
+    public StorageManager(Context context, Looper looper) throws ServiceNotFoundException {
         mContext = context;
         mResolver = context.getContentResolver();
         mLooper = looper;
-        mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
-        if (mMountService == null) {
-            throw new IllegalStateException("Failed to find running mount service");
-        }
+        mMountService = IMountService.Stub.asInterface(ServiceManager.getServiceOrThrow("mount"));
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0b082de..bff4d7d 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6026,6 +6026,17 @@
         public static final String ASSIST_SCREENSHOT_ENABLED = "assist_screenshot_enabled";
 
         /**
+         * Specifies whether the screen will show an animation if screen contents are sent to the
+         * assist application (active voice interaction service).
+         *
+         * Note that the disclosure will be forced for third-party assistants or if the device
+         * does not support disabling it.
+         *
+         * @hide
+         */
+        public static final String ASSIST_DISCLOSURE_ENABLED = "assist_disclosure_enabled";
+
+        /**
          * Names of the service components that the current user has explicitly allowed to
          * see all of the user's notifications, separated by ':'.
          *
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index cfeed51..0f92ed0 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -163,10 +163,9 @@
     /**
      * Retrieves available information about this device's flash lock state.
      *
-     * @return FLASH_LOCK_STATE_LOCKED if device bootloader is locked,
-     * FLASH_LOCK_STATE_UNLOCKED if device bootloader is unlocked,
-     * or FLASH_LOCK_STATE unknown if this information cannot be ascertained
-     * on this device.
+     * @return {@link #FLASH_LOCK_LOCKED} if device bootloader is locked,
+     * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN}
+     * if this information cannot be ascertained on this device.
      */
     @FlashLockState
     public int getFlashLockState() {
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index 3855ff3..24c119f 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -29,6 +29,9 @@
 /**
  * A movement method that traverses links in the text buffer and scrolls if necessary.
  * Supports clicking on links with DPad Center or Enter.
+ *
+ * <p>Note: Starting from Android 8.0 (API level 25) this class no longer handles the touch
+ * clicks.
  */
 public class LinkMovementMethod extends ScrollingMovementMethod {
     private static final int CLICK = 1;
@@ -98,14 +101,14 @@
 
         int padding = widget.getTotalPaddingTop() +
                       widget.getTotalPaddingBottom();
-        int areatop = widget.getScrollY();
-        int areabot = areatop + widget.getHeight() - padding;
+        int areaTop = widget.getScrollY();
+        int areaBot = areaTop + widget.getHeight() - padding;
 
-        int linetop = layout.getLineForVertical(areatop);
-        int linebot = layout.getLineForVertical(areabot);
+        int lineTop = layout.getLineForVertical(areaTop);
+        int lineBot = layout.getLineForVertical(areaBot);
 
-        int first = layout.getLineStart(linetop);
-        int last = layout.getLineEnd(linebot);
+        int first = layout.getLineStart(lineTop);
+        int last = layout.getLineEnd(lineBot);
 
         ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);
 
@@ -141,46 +144,46 @@
             break;
 
         case UP:
-            int beststart, bestend;
+            int bestStart, bestEnd;
 
-            beststart = -1;
-            bestend = -1;
+            bestStart = -1;
+            bestEnd = -1;
 
             for (int i = 0; i < candidates.length; i++) {
                 int end = buffer.getSpanEnd(candidates[i]);
 
                 if (end < selEnd || selStart == selEnd) {
-                    if (end > bestend) {
-                        beststart = buffer.getSpanStart(candidates[i]);
-                        bestend = end;
+                    if (end > bestEnd) {
+                        bestStart = buffer.getSpanStart(candidates[i]);
+                        bestEnd = end;
                     }
                 }
             }
 
-            if (beststart >= 0) {
-                Selection.setSelection(buffer, bestend, beststart);
+            if (bestStart >= 0) {
+                Selection.setSelection(buffer, bestEnd, bestStart);
                 return true;
             }
 
             break;
 
         case DOWN:
-            beststart = Integer.MAX_VALUE;
-            bestend = Integer.MAX_VALUE;
+            bestStart = Integer.MAX_VALUE;
+            bestEnd = Integer.MAX_VALUE;
 
             for (int i = 0; i < candidates.length; i++) {
                 int start = buffer.getSpanStart(candidates[i]);
 
                 if (start > selStart || selStart == selEnd) {
-                    if (start < beststart) {
-                        beststart = start;
-                        bestend = buffer.getSpanEnd(candidates[i]);
+                    if (start < bestStart) {
+                        bestStart = start;
+                        bestEnd = buffer.getSpanEnd(candidates[i]);
                     }
                 }
             }
 
-            if (bestend < Integer.MAX_VALUE) {
-                Selection.setSelection(buffer, beststart, bestend);
+            if (bestEnd < Integer.MAX_VALUE) {
+                Selection.setSelection(buffer, bestStart, bestEnd);
                 return true;
             }
 
@@ -195,8 +198,7 @@
                                 MotionEvent event) {
         int action = event.getAction();
 
-        if (action == MotionEvent.ACTION_UP ||
-            action == MotionEvent.ACTION_DOWN) {
+        if (action == MotionEvent.ACTION_DOWN) {
             int x = (int) event.getX();
             int y = (int) event.getY();
 
@@ -210,17 +212,12 @@
             int line = layout.getLineForVertical(y);
             int off = layout.getOffsetForHorizontal(line, x);
 
-            ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
+            ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);
 
-            if (link.length != 0) {
-                if (action == MotionEvent.ACTION_UP) {
-                    link[0].onClick(widget);
-                } else if (action == MotionEvent.ACTION_DOWN) {
-                    Selection.setSelection(buffer,
-                                           buffer.getSpanStart(link[0]),
-                                           buffer.getSpanEnd(link[0]));
-                }
-
+            if (links.length != 0) {
+                Selection.setSelection(buffer,
+                        buffer.getSpanStart(links[0]),
+                        buffer.getSpanEnd(links[0]));
                 return true;
             } else {
                 Selection.removeSelection(buffer);
diff --git a/core/java/android/util/TimedRemoteCaller.java b/core/java/android/util/TimedRemoteCaller.java
index abb2b64..100c16e 100644
--- a/core/java/android/util/TimedRemoteCaller.java
+++ b/core/java/android/util/TimedRemoteCaller.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import android.os.SystemClock;
+import com.android.internal.annotations.GuardedBy;
 
 import java.util.concurrent.TimeoutException;
 
@@ -29,8 +30,7 @@
  * the sequence number. If the response comes within the timeout
  * and its sequence number is the one sent in the method invocation,
  * then the call succeeded. If the response does not come within
- * the timeout then the call failed. Older result received when
- * waiting for the result are ignored.
+ * the timeout then the call failed.
  * <p>
  * Typical usage is:
  * </p>
@@ -66,66 +66,90 @@
 
     public static final long DEFAULT_CALL_TIMEOUT_MILLIS = 5000;
 
-    private static final int UNDEFINED_SEQUENCE = -1;
-
     private final Object mLock = new Object();
 
     private final long mCallTimeoutMillis;
 
+    /** The callbacks we are waiting for, key == sequence id, value == 1 */
+    @GuardedBy("mLock")
+    private final SparseIntArray mAwaitedCalls = new SparseIntArray(1);
+
+    /** The callbacks we received but for which the result has not yet been reported */
+    @GuardedBy("mLock")
+    private final SparseArray<T> mReceivedCalls = new SparseArray<>(1);
+
+    @GuardedBy("mLock")
     private int mSequenceCounter;
 
-    private int mReceivedSequence = UNDEFINED_SEQUENCE;
-
-    private int mAwaitedSequence = UNDEFINED_SEQUENCE;
-
-    private T mResult;
-
+    /**
+     * Create a new timed caller.
+     *
+     * @param callTimeoutMillis The time to wait in {@link #getResultTimed} before a timed call will
+     *                          be declared timed out
+     */
     public TimedRemoteCaller(long callTimeoutMillis) {
         mCallTimeoutMillis = callTimeoutMillis;
     }
 
-    public final int onBeforeRemoteCall() {
+    /**
+     * Indicate that a timed call will be made.
+     *
+     * @return The sequence id for the call
+     */
+    protected final int onBeforeRemoteCall() {
         synchronized (mLock) {
-            mAwaitedSequence = mSequenceCounter++;
-            return mAwaitedSequence;
+            int sequenceId;
+            do {
+                sequenceId = mSequenceCounter++;
+            } while (mAwaitedCalls.get(sequenceId) != 0);
+
+            mAwaitedCalls.put(sequenceId, 1);
+
+            return sequenceId;
         }
     }
 
-    public final T getResultTimed(int sequence) throws TimeoutException {
+    /**
+     * Indicate that the timed call has returned.
+     *
+     * @param result The result of the timed call
+     * @param sequence The sequence id of the call (from {@link #onBeforeRemoteCall()})
+     */
+    protected final void onRemoteMethodResult(T result, int sequence) {
         synchronized (mLock) {
-            final boolean success = waitForResultTimedLocked(sequence);
-            if (!success) {
-                throw new TimeoutException("No reponse for sequence: " + sequence);
-            }
-            T result = mResult;
-            mResult = null;
-            return result;
-        }
-    }
-
-    public final void onRemoteMethodResult(T result, int sequence) {
-        synchronized (mLock) {
-            if (sequence == mAwaitedSequence) {
-                mReceivedSequence = sequence;
-                mResult = result;
+            // Do nothing if we do not await the call anymore as it must have timed out
+            boolean containedSequenceId = mAwaitedCalls.get(sequence) != 0;
+            if (containedSequenceId) {
+                mAwaitedCalls.delete(sequence);
+                mReceivedCalls.put(sequence, result);
                 mLock.notifyAll();
             }
         }
     }
 
-    private boolean waitForResultTimedLocked(int sequence) {
+    /**
+     * Wait until the timed call has returned.
+     *
+     * @param sequence The sequence id of the call (from {@link #onBeforeRemoteCall()})
+     *
+     * @return The result of the timed call (set in {@link #onRemoteMethodResult(Object, int)})
+     */
+    protected final T getResultTimed(int sequence) throws TimeoutException {
         final long startMillis = SystemClock.uptimeMillis();
         while (true) {
             try {
-                if (mReceivedSequence == sequence) {
-                    return true;
+                synchronized (mLock) {
+                    if (mReceivedCalls.indexOfKey(sequence) >= 0) {
+                        return mReceivedCalls.removeReturnOld(sequence);
+                    }
+                    final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
+                    final long waitMillis = mCallTimeoutMillis - elapsedMillis;
+                    if (waitMillis <= 0) {
+                        mAwaitedCalls.delete(sequence);
+                        throw new TimeoutException("No response for sequence: " + sequence);
+                    }
+                    mLock.wait(waitMillis);
                 }
-                final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
-                final long waitMillis = mCallTimeoutMillis - elapsedMillis;
-                if (waitMillis <= 0) {
-                    return false;
-                }
-                mLock.wait(waitMillis);
             } catch (InterruptedException ie) {
                 /* ignore */
             }
diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java
index 4a77af4..8d891bb 100644
--- a/core/java/android/view/SoundEffectConstants.java
+++ b/core/java/android/view/SoundEffectConstants.java
@@ -37,6 +37,8 @@
      *     or {@link View#FOCUS_BACKWARD}
 
      * @return The appropriate sonification constant.
+     * @throws {@link IllegalArgumentException} when the passed direction is not one of the
+     *     documented values.
      */
     public static int getContantForFocusDirection(int direction) {
         switch (direction) {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 745da51..bb77100 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -229,7 +229,6 @@
     @Override
     protected void destroyHardwareResources() {
         destroyHardwareLayer();
-        mUpdateSurface = mSurface != null;
     }
 
     private void destroyHardwareLayer() {
@@ -376,17 +375,17 @@
             }
 
             mLayer = mAttachInfo.mThreadedRenderer.createTextureLayer();
-            if (!mUpdateSurface) {
+            boolean createNewSurface = (mSurface == null);
+            if (createNewSurface) {
                 // Create a new SurfaceTexture for the layer.
                 mSurface = new SurfaceTexture(false);
                 mLayer.setSurfaceTexture(mSurface);
                 nCreateNativeWindow(mSurface);
             }
             mSurface.setDefaultBufferSize(getWidth(), getHeight());
-
             mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
 
-            if (mListener != null && !mUpdateSurface) {
+            if (mListener != null && createNewSurface) {
                 mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
             }
             mLayer.setLayerPaint(mLayerPaint);
@@ -745,9 +744,11 @@
                     "released SurfaceTexture");
         }
         if (mSurface != null) {
+            nDestroyNativeWindow();
             mSurface.release();
         }
         mSurface = surfaceTexture;
+        nCreateNativeWindow(mSurface);
 
         /*
          * If the view is visible and we already made a layer, update the
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 8ce9ddb..1034275 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -520,16 +520,6 @@
     }
 
     /**
-     * This method should be invoked whenever the current threaded renderer
-     * context should be reset.
-     *
-     * @param surface The surface to render
-     */
-    void invalidate(Surface surface) {
-        updateSurface(surface);
-    }
-
-    /**
      * Detaches the layer's surface texture from the GL context and releases
      * the texture id
      */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c37cf56..5a7f0ff 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20656,7 +20656,6 @@
      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
-     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
@@ -20674,6 +20673,9 @@
             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
             return false;
         }
+
+        data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
+
         boolean okay = false;
 
         Point shadowSize = new Point();
@@ -23864,7 +23866,7 @@
      * on the screen.
      */
     private boolean shouldDrawRoundScrollbar() {
-        if (!mResources.getConfiguration().isScreenRound()) {
+        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
             return false;
         }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2bc1d74..757727b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5539,6 +5539,10 @@
                 // Remember who the current drag target is pre-dispatch
                 final View prevDragView = mCurrentDragView;
 
+                if (what == DragEvent.ACTION_DROP) {
+                    event.getClipData().prepareToEnterProcess();
+                }
+
                 // Now dispatch the drag/drop event
                 boolean result = mView.dispatchDragEvent(event);
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index f1fa216..0b9f9d0 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -484,6 +484,7 @@
         public void switchInputMethod(boolean forwardDirection);
 
         public void shutdown(boolean confirm);
+        public void reboot(boolean confirm);
         public void rebootSafeMode(boolean confirm);
 
         /**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c0c8e64..e37cf96 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -41,6 +41,7 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.Trace;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.text.TextUtils;
 import android.text.style.SuggestionSpan;
 import android.util.Log;
@@ -55,6 +56,7 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewRootImpl;
+import android.view.textservice.TextServicesManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -622,6 +624,11 @@
 
     final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
 
+    InputMethodManager(Looper looper) throws ServiceNotFoundException {
+        this(IInputMethodManager.Stub.asInterface(
+                ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE)), looper);
+    }
+
     InputMethodManager(IInputMethodManager service, Looper looper) {
         mService = service;
         mMainLooper = looper;
@@ -638,9 +645,11 @@
     public static InputMethodManager getInstance() {
         synchronized (InputMethodManager.class) {
             if (sInstance == null) {
-                IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
-                IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
-                sInstance = new InputMethodManager(service, Looper.getMainLooper());
+                try {
+                    sInstance = new InputMethodManager(Looper.getMainLooper());
+                } catch (ServiceNotFoundException e) {
+                    throw new IllegalStateException(e);
+                }
             }
             return sInstance;
         }
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 89d879e..0f168f3 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -16,16 +16,16 @@
 
 package android.view.textservice;
 
-import com.android.internal.textservice.ITextServicesManager;
-
 import android.content.Context;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.Log;
 import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
 
+import com.android.internal.textservice.ITextServicesManager;
+
 import java.util.Locale;
 
 /**
@@ -66,13 +66,12 @@
     private static final boolean DBG = false;
 
     private static TextServicesManager sInstance;
-    private static ITextServicesManager sService;
 
-    private TextServicesManager() {
-        if (sService == null) {
-            IBinder b = ServiceManager.getService(Context.TEXT_SERVICES_MANAGER_SERVICE);
-            sService = ITextServicesManager.Stub.asInterface(b);
-        }
+    private final ITextServicesManager mService;
+
+    private TextServicesManager() throws ServiceNotFoundException {
+        mService = ITextServicesManager.Stub.asInterface(
+                ServiceManager.getServiceOrThrow(Context.TEXT_SERVICES_MANAGER_SERVICE));
     }
 
     /**
@@ -81,12 +80,15 @@
      */
     public static TextServicesManager getInstance() {
         synchronized (TextServicesManager.class) {
-            if (sInstance != null) {
-                return sInstance;
+            if (sInstance == null) {
+                try {
+                    sInstance = new TextServicesManager();
+                } catch (ServiceNotFoundException e) {
+                    throw new IllegalStateException(e);
+                }
             }
-            sInstance = new TextServicesManager();
+            return sInstance;
         }
-        return sInstance;
     }
 
     /**
@@ -131,7 +133,7 @@
 
         final SpellCheckerInfo sci;
         try {
-            sci = sService.getCurrentSpellChecker(null);
+            sci = mService.getCurrentSpellChecker(null);
         } catch (RemoteException e) {
             return null;
         }
@@ -170,13 +172,13 @@
             return null;
         }
         final SpellCheckerSession session = new SpellCheckerSession(
-                sci, sService, listener, subtypeInUse);
+                sci, mService, listener, subtypeInUse);
         try {
-            sService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
+            mService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
                     session.getTextServicesSessionListener(),
                     session.getSpellCheckerSessionListener(), bundle);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
         return session;
     }
@@ -186,14 +188,13 @@
      */
     public SpellCheckerInfo[] getEnabledSpellCheckers() {
         try {
-            final SpellCheckerInfo[] retval = sService.getEnabledSpellCheckers();
+            final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers();
             if (DBG) {
                 Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null"));
             }
             return retval;
         } catch (RemoteException e) {
-            Log.e(TAG, "Error in getEnabledSpellCheckers: " + e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -203,9 +204,9 @@
     public SpellCheckerInfo getCurrentSpellChecker() {
         try {
             // Passing null as a locale for ICS
-            return sService.getCurrentSpellChecker(null);
+            return mService.getCurrentSpellChecker(null);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -217,9 +218,9 @@
             if (sci == null) {
                 throw new NullPointerException("SpellCheckerInfo is null.");
             }
-            sService.setCurrentSpellChecker(null, sci.getId());
+            mService.setCurrentSpellChecker(null, sci.getId());
         } catch (RemoteException e) {
-            Log.e(TAG, "Error in setCurrentSpellChecker: " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -229,17 +230,10 @@
     public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
             boolean allowImplicitlySelectedSubtype) {
         try {
-            if (sService == null) {
-                // TODO: This is a workaround. Needs to investigate why sService could be null
-                // here.
-                Log.e(TAG, "sService is null.");
-                return null;
-            }
             // Passing null as a locale until we support multiple enabled spell checker subtypes.
-            return sService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
+            return mService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
         } catch (RemoteException e) {
-            Log.e(TAG, "Error in getCurrentSpellCheckerSubtype: " + e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -254,9 +248,9 @@
             } else {
                 hashCode = subtype.hashCode();
             }
-            sService.setCurrentSpellCheckerSubtype(null, hashCode);
+            mService.setCurrentSpellCheckerSubtype(null, hashCode);
         } catch (RemoteException e) {
-            Log.e(TAG, "Error in setSpellCheckerSubtype:" + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -265,9 +259,9 @@
      */
     public void setSpellCheckerEnabled(boolean enabled) {
         try {
-            sService.setSpellCheckerEnabled(enabled);
+            mService.setSpellCheckerEnabled(enabled);
         } catch (RemoteException e) {
-            Log.e(TAG, "Error in setSpellCheckerEnabled:" + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -276,10 +270,9 @@
      */
     public boolean isSpellCheckerEnabled() {
         try {
-            return sService.isSpellCheckerEnabled();
+            return mService.isSpellCheckerEnabled();
         } catch (RemoteException e) {
-            Log.e(TAG, "Error in isSpellCheckerEnabled:" + e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 66b22ce..5ed6638 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1546,7 +1546,7 @@
         switch (action) {
             case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
             case R.id.accessibilityActionScrollDown: {
-                if (isEnabled() && getLastVisiblePosition() < getCount() - 1) {
+                if (isEnabled() && canScrollDown()) {
                     final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
                     smoothScrollBy(viewportHeight, PositionScroller.SCROLL_DURATION);
                     return true;
@@ -1554,7 +1554,7 @@
             } return false;
             case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
             case R.id.accessibilityActionScrollUp: {
-                if (isEnabled() && mFirstPosition > 0) {
+                if (isEnabled() && canScrollUp()) {
                     final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
                     smoothScrollBy(-viewportHeight, PositionScroller.SCROLL_DURATION);
                     return true;
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 02ee2df..6f198e7 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -16,7 +16,11 @@
 
 package android.widget;
 
+import com.android.internal.R;
+import com.android.internal.widget.ExploreByTouchHelper;
+
 import android.animation.ObjectAnimator;
+import android.annotation.IntDef;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -43,9 +47,8 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
-import com.android.internal.R;
-import com.android.internal.widget.ExploreByTouchHelper;
-
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Calendar;
 import java.util.Locale;
 
@@ -55,11 +58,16 @@
  * @hide
  */
 public class RadialTimePickerView extends View {
-
     private static final String TAG = "RadialTimePickerView";
 
     public static final int HOURS = 0;
     public static final int MINUTES = 1;
+
+    /** @hide */
+    @IntDef({HOURS, MINUTES})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface PickerType {}
+
     private static final int HOURS_INNER = 2;
 
     private static final int SELECTOR_CIRCLE = 0;
@@ -185,8 +193,24 @@
 
     private boolean mInputEnabled = true;
 
-    public interface OnValueSelectedListener {
-        void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance);
+    interface OnValueSelectedListener {
+        /**
+         * Called when the selected value at a given picker index has changed.
+         *
+         * @param pickerType the type of value that has changed, one of:
+         *                   <ul>
+         *                       <li>{@link #MINUTES}
+         *                       <li>{@link #HOURS}
+         *                   </ul>
+         * @param newValue the new value as minute in hour (0-59) or hour in
+         *                 day (0-23)
+         * @param autoAdvance when the picker type is {@link #HOURS},
+         *                    {@code true} to switch to the {@link #MINUTES}
+         *                    picker or {@code false} to stay on the current
+         *                    picker. No effect when picker type is
+         *                    {@link #MINUTES}.
+         */
+        void onValueSelected(@PickerType int pickerType, int newValue, boolean autoAdvance);
     }
 
     /**
@@ -977,7 +1001,7 @@
         // Ensure we're showing the correct picker.
         animatePicker(mShowHours, ANIM_DURATION_TOUCH);
 
-        final int type;
+        final @PickerType int type;
         final int newValue;
         final boolean valueChanged;
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a6d004f..6dafe34 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -114,6 +114,7 @@
 import android.view.Choreographer;
 import android.view.ContextMenu;
 import android.view.DragEvent;
+import android.view.GestureDetector;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyCharacterMap;
@@ -650,6 +651,8 @@
      */
     private Editor mEditor;
 
+    private final GestureDetector mClickableSpanOnClickGestureDetector;
+
     private static final int DEVICE_PROVISIONED_UNKNOWN = 0;
     private static final int DEVICE_PROVISIONED_NO = 1;
     private static final int DEVICE_PROVISIONED_YES = 2;
@@ -1488,6 +1491,24 @@
         if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
+
+        mClickableSpanOnClickGestureDetector = new GestureDetector(context,
+                new GestureDetector.SimpleOnGestureListener() {
+                    @Override
+                    public boolean onSingleTapConfirmed(MotionEvent e) {
+                        if (mLinksClickable && (mMovement != null) &&
+                                (mMovement instanceof LinkMovementMethod
+                                || (mAutoLinkMask != 0 && isTextSelectable()))) {
+                            ClickableSpan[] links = ((Spannable) mText).getSpans(
+                                    getSelectionStart(), getSelectionEnd(), ClickableSpan.class);
+                            if (links.length > 0) {
+                                links[0].onClick(TextView.this);
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+                });
     }
 
     private int[] parseDimensionArray(TypedArray dimens) {
@@ -8515,21 +8536,9 @@
             if (mMovement != null) {
                 handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
             }
+            handled |= mClickableSpanOnClickGestureDetector.onTouchEvent(event);
 
             final boolean textIsSelectable = isTextSelectable();
-            if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) {
-                // The LinkMovementMethod which should handle taps on links has not been installed
-                // on non editable text that support text selection.
-                // We reproduce its behavior here to open links for these.
-                ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
-                        getSelectionEnd(), ClickableSpan.class);
-
-                if (links.length > 0) {
-                    links[0].onClick(this);
-                    handled = true;
-                }
-            }
-
             if (touchIsFinished && (isTextEditable() || textIsSelectable)) {
                 // Show the IME, except when selecting in read-only text.
                 final InputMethodManager imm = InputMethodManager.peekInstance();
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 59cde5b..1d37a21 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -62,9 +62,6 @@
     private static final int HOUR_INDEX = RadialTimePickerView.HOURS;
     private static final int MINUTE_INDEX = RadialTimePickerView.MINUTES;
 
-    // NOT a real index for the purpose of what's showing.
-    private static final int AMPM_INDEX = 2;
-
     private static final int[] ATTRS_TEXT_COLOR = new int[] {R.attr.textColor};
     private static final int[] ATTRS_DISABLED_ALPHA = new int[] {R.attr.disabledAlpha};
 
@@ -725,22 +722,21 @@
     /** Listener for RadialTimePickerView interaction. */
     private final OnValueSelectedListener mOnValueSelectedListener = new OnValueSelectedListener() {
         @Override
-        public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
-            switch (pickerIndex) {
-                case HOUR_INDEX:
+        public void onValueSelected(int pickerType, int newValue, boolean autoAdvance) {
+            switch (pickerType) {
+                case RadialTimePickerView.HOURS:
                     final boolean isTransition = mAllowAutoAdvance && autoAdvance;
                     setHourInternal(newValue, true, !isTransition);
                     if (isTransition) {
                         setCurrentItemShowing(MINUTE_INDEX, true, false);
-                        mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes);
+
+                        final int localizedHour = getLocalizedHour(newValue);
+                        mDelegator.announceForAccessibility(localizedHour + ". " + mSelectMinutes);
                     }
                     break;
-                case MINUTE_INDEX:
+                case RadialTimePickerView.MINUTES:
                     setMinuteInternal(newValue, true);
                     break;
-                case AMPM_INDEX:
-                    updateAmPmLabelStates(newValue);
-                    break;
             }
 
             if (mOnTimeChangedListener != null) {
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 56c5cc9..2940079 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -16,10 +16,13 @@
 
 package com.android.internal.app;
 
+import com.android.internal.R;
+
 import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
@@ -166,4 +169,41 @@
         return null;
     }
 
+    public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) {
+        if (assistant == null) {
+            return false;
+        }
+        ApplicationInfo applicationInfo;
+        try {
+            applicationInfo = context.getPackageManager().getApplicationInfo(
+                    assistant.getPackageName(), 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+        return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp();
+    }
+
+    private static boolean isDisclosureEnabled(Context context) {
+        return Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0;
+    }
+
+    /**
+     * @return if the disclosure animation should trigger for the given assistant.
+     *
+     * Third-party assistants will always need to disclose, while the user can configure this for
+     * pre-installed assistants.
+     */
+    public static boolean shouldDisclose(Context context, ComponentName assistant) {
+        if (!allowDisablingAssistDisclosure(context)) {
+            return true;
+        }
+
+        return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant);
+    }
+
+    public static boolean allowDisablingAssistDisclosure(Context context) {
+        return context.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowDisablingAssistDisclosure);
+    }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fef4a53..0aa3a7e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -111,7 +111,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 149 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 150 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -1425,22 +1425,6 @@
             mUnpluggedReportedCount = 0;
             return true;
         }
-
-        @Override
-        public void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
-            super.writeSummaryFromParcelLocked(out, batteryRealtime);
-            out.writeLong(mCurrentReportedTotalTime);
-            out.writeInt(mCurrentReportedCount);
-            out.writeInt(mTrackingReportedValues ? 1 : 0);
-        }
-
-        @Override
-        public void readSummaryFromParcelLocked(Parcel in) {
-            super.readSummaryFromParcelLocked(in);
-            mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
-            mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
-            mTrackingReportedValues = in.readInt() == 1;
-        }
     }
 
     /**
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 7a4f74f..40b9ab6 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -502,21 +502,42 @@
                 // System server is fully AOTed and never profiled
                 // for profile guided compilation.
                 // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
-                final int dexoptNeeded = DexFile.getDexOptNeeded(
+
+                int dexoptNeeded;
+                try {
+                    dexoptNeeded = DexFile.getDexOptNeeded(
                         classPathElement, instructionSet, "speed",
                         false /* newProfile */);
-                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                    installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
-                            dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
-                            sharedLibraries);
+                } catch (FileNotFoundException ignored) {
+                    // Do not add to the classpath.
+                    Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
+                    continue;
+                } catch (IOException e) {
+                    // Not fully clear what to do here as we don't know the cause of the
+                    // IO exception. Add to the classpath to be conservative, but don't
+                    // attempt to compile it.
+                    Log.w(TAG, "Error checking classpath element for system server: "
+                            + classPathElement, e);
+                    dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
                 }
+
+                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+                    try {
+                        installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
+                                dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
+                                sharedLibraries);
+                    } catch (InstallerException e) {
+                        // Ignore (but log), we need this on the classpath for fallback mode.
+                        Log.w(TAG, "Failed compiling classpath element for system server: "
+                                + classPathElement, e);
+                    }
+                }
+
                 if (!sharedLibraries.isEmpty()) {
                     sharedLibraries += ":";
                 }
                 sharedLibraries += classPathElement;
             }
-        } catch (IOException | InstallerException e) {
-            throw new RuntimeException("Error starting system_server", e);
         } finally {
             installer.disconnect();
         }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 9ad750d..878f3a6 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -92,8 +92,6 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.TypedValue;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.widget.FrameLayout;
@@ -2057,9 +2055,6 @@
     }
 
     static private final String FOCUSED_ID_TAG = "android:focusedViewId";
-    static private final String ACCESSIBILITY_FOCUSED_ID_TAG = "android:accessibilityFocusedViewId";
-    static private final String ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG =
-            "android:accessibilityFocusedVirtualViewId";
     static private final String VIEWS_TAG = "android:views";
     static private final String PANELS_TAG = "android:Panels";
     static private final String ACTION_BAR_TAG = "android:ActionBar";
@@ -2082,26 +2077,6 @@
             outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
         }
 
-        // Save the accessibility focused view ID.
-        if (mDecor != null) {
-            final ViewRootImpl viewRootImpl = mDecor.getViewRootImpl();
-            if (viewRootImpl != null) {
-                final View accessFocusHost = viewRootImpl.getAccessibilityFocusedHost();
-                if (accessFocusHost != null && accessFocusHost.getId() != View.NO_ID) {
-                    outState.putInt(ACCESSIBILITY_FOCUSED_ID_TAG, accessFocusHost.getId());
-
-                    // If we have a focused virtual node ID, save that too.
-                    final AccessibilityNodeInfo accessFocusedNode =
-                            viewRootImpl.getAccessibilityFocusedVirtualView();
-                    if (accessFocusedNode != null) {
-                        final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
-                                accessFocusedNode.getSourceNodeId());
-                        outState.putInt(ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, virtualNodeId);
-                    }
-                }
-            }
-        }
-
         // save the panels
         SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
         savePanelState(panelStates);
@@ -2144,13 +2119,6 @@
             }
         }
 
-        // Restore the accessibility focused view.
-        final int accessFocusHostViewId = savedInstanceState.getInt(
-                ACCESSIBILITY_FOCUSED_ID_TAG, View.NO_ID);
-        final int accessFocusVirtualViewId = savedInstanceState.getInt(
-                ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, AccessibilityNodeInfo.UNDEFINED_ITEM_ID);
-        tryRestoreAccessibilityFocus(accessFocusHostViewId, accessFocusVirtualViewId);
-
         // Restore the panels.
         SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
         if (panelStates != null) {
@@ -2170,33 +2138,6 @@
         }
     }
 
-    private void tryRestoreAccessibilityFocus(int hostViewId, int virtualViewId) {
-        if (hostViewId != View.NO_ID && mDecor != null) {
-            final View needsAccessFocus = mDecor.findViewById(hostViewId);
-            if (needsAccessFocus != null) {
-                if (!tryFocusingVirtualView(needsAccessFocus, virtualViewId)
-                        && !needsAccessFocus.requestAccessibilityFocus()) {
-                    Log.w(TAG, "Failed to restore focus to previously accessibility"
-                            + " focused view with id " + hostViewId);
-                }
-            } else {
-                Log.w(TAG, "Previously accessibility focused view reported id " + hostViewId
-                        + " during save, but can't be found during restore.");
-            }
-        }
-    }
-
-    private boolean tryFocusingVirtualView(View host, int virtualViewId) {
-        if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-            final AccessibilityNodeProvider nodeProvider = host.getAccessibilityNodeProvider();
-            if (nodeProvider != null) {
-                return nodeProvider.performAction(virtualViewId,
-                        AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
-            }
-        }
-        return false;
-    }
-
     /**
      * Invoked when the panels should freeze their state.
      *
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2a79d28..0e07bf8 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -288,7 +288,6 @@
     public void reportFailedPasswordAttempt(int userId) {
         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
-        requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL, userId);
     }
 
     public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1550,7 +1549,8 @@
                 value = { STRONG_AUTH_NOT_REQUIRED,
                         STRONG_AUTH_REQUIRED_AFTER_BOOT,
                         STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
-                        SOME_AUTH_REQUIRED_AFTER_USER_REQUEST})
+                        SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
+                        STRONG_AUTH_REQUIRED_AFTER_LOCKOUT})
         @Retention(RetentionPolicy.SOURCE)
         public @interface StrongAuthFlags {}
 
@@ -1581,13 +1581,12 @@
         public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
 
         /**
-         * Some authentication is required because the user has entered a wrong credential.
+         * Strong auth flags that do not prevent fingerprint from being accepted as auth.
+         *
+         * If any other flags are set, fingerprint is disabled.
          */
-        public static final int SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL = 0x10;
-
         private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
-                | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST
-                | SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL;
+                | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 
         private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
         private final H mHandler;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 23e291f..ffa7107 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -58,21 +58,19 @@
 #endif
 
 // For both of these, err should be in the errno range (positive), not a status_t (negative)
-
-static void signalExceptionForPriorityError(JNIEnv* env, int err)
-{
+static void signalExceptionForError(JNIEnv* env, int err, int tid) {
     switch (err) {
         case EINVAL:
-            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                 "Invalid argument: %d", tid);
             break;
         case ESRCH:
-            jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
+            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                 "Given thread %d does not exist", tid);
             break;
         case EPERM:
-            jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
-            break;
-        case EACCES:
-            jniThrowException(env, "java/lang/SecurityException", "No permission to set to given priority");
+            jniThrowExceptionFmt(env, "java/lang/SecurityException",
+                                 "No permission to modify given thread %d", tid);
             break;
         default:
             jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
@@ -80,23 +78,27 @@
     }
 }
 
-static void signalExceptionForGroupError(JNIEnv* env, int err)
-{
+static void signalExceptionForPriorityError(JNIEnv* env, int err, int tid) {
     switch (err) {
-        case EINVAL:
-            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-            break;
-        case ESRCH:
-            jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
-            break;
-        case EPERM:
-            jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
-            break;
         case EACCES:
-            jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group");
+            jniThrowExceptionFmt(env, "java/lang/SecurityException",
+                                 "No permission to set the priority of %d", tid);
             break;
         default:
-            jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
+            signalExceptionForError(env, err, tid);
+            break;
+    }
+
+}
+
+static void signalExceptionForGroupError(JNIEnv* env, int err, int tid) {
+    switch (err) {
+        case EACCES:
+            jniThrowExceptionFmt(env, "java/lang/SecurityException",
+                                 "No permission to set the group of %d", tid);
+            break;
+        default:
+            signalExceptionForError(env, err, tid);
             break;
     }
 }
@@ -171,7 +173,7 @@
     SchedPolicy sp = (SchedPolicy) grp;
     int res = set_sched_policy(tid, sp);
     if (res != NO_ERROR) {
-        signalExceptionForGroupError(env, -res);
+        signalExceptionForGroupError(env, -res, tid);
     }
 }
 
@@ -183,7 +185,7 @@
     struct dirent *de;
 
     if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) {
-        signalExceptionForGroupError(env, EINVAL);
+        signalExceptionForGroupError(env, EINVAL, pid);
         return;
     }
 
@@ -219,7 +221,7 @@
     if (!(d = opendir(proc_path))) {
         // If the process exited on us, don't generate an exception
         if (errno != ENOENT)
-            signalExceptionForGroupError(env, errno);
+            signalExceptionForGroupError(env, errno, pid);
         return;
     }
 
@@ -254,7 +256,7 @@
 #ifdef ENABLE_CPUSETS
                 int err = set_cpuset_policy(t_pid, sp);
                 if (err != NO_ERROR) {
-                    signalExceptionForGroupError(env, -err);
+                    signalExceptionForGroupError(env, -err, t_pid);
                     break;
                 }
 #endif
@@ -266,14 +268,14 @@
         // set both cpuset and cgroup for general threads
         err = set_cpuset_policy(t_pid, sp);
         if (err != NO_ERROR) {
-            signalExceptionForGroupError(env, -err);
+            signalExceptionForGroupError(env, -err, t_pid);
             break;
         }
 #endif
 
         err = set_sched_policy(t_pid, sp);
         if (err != NO_ERROR) {
-            signalExceptionForGroupError(env, -err);
+            signalExceptionForGroupError(env, -err, t_pid);
             break;
         }
 
@@ -285,7 +287,7 @@
 {
     SchedPolicy sp;
     if (get_sched_policy(pid, &sp) != 0) {
-        signalExceptionForGroupError(env, errno);
+        signalExceptionForGroupError(env, errno, pid);
     }
     return (int) sp;
 }
@@ -400,7 +402,7 @@
     jintArray cpus;
     int pid = getpid();
     if (get_sched_policy(pid, &sp) != 0) {
-        signalExceptionForGroupError(env, errno);
+        signalExceptionForGroupError(env, errno, pid);
         return NULL;
     }
     get_exclusive_cpuset_cores(sp, &cpu_set);
@@ -449,10 +451,10 @@
     errno = 0;
     policy = sched_getscheduler(tid);
     if (errno != 0) {
-        signalExceptionForPriorityError(env, errno);
+        signalExceptionForPriorityError(env, errno, tid);
     }
 #else
-    signalExceptionForPriorityError(env, ENOSYS);
+    signalExceptionForPriorityError(env, ENOSYS, tid);
 #endif
     return policy;
 }
@@ -466,10 +468,10 @@
     param.sched_priority = pri;
     int rc = sched_setscheduler(tid, policy, &param);
     if (rc) {
-        signalExceptionForPriorityError(env, errno);
+        signalExceptionForPriorityError(env, errno, tid);
     }
 #else
-    signalExceptionForPriorityError(env, ENOSYS);
+    signalExceptionForPriorityError(env, ENOSYS, tid);
 #endif
 }
 
@@ -494,9 +496,9 @@
     int rc = androidSetThreadPriority(pid, pri);
     if (rc != 0) {
         if (rc == INVALID_OPERATION) {
-            signalExceptionForPriorityError(env, errno);
+            signalExceptionForPriorityError(env, errno, pid);
         } else {
-            signalExceptionForGroupError(env, errno);
+            signalExceptionForGroupError(env, errno, pid);
         }
     }
 
@@ -516,7 +518,7 @@
     errno = 0;
     jint pri = getpriority(PRIO_PROCESS, pid);
     if (errno != 0) {
-        signalExceptionForPriorityError(env, errno);
+        signalExceptionForPriorityError(env, errno, pid);
     }
     //ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri);
     return pri;
diff --git a/core/res/res/drawable/ic_lock_power_off.xml b/core/res/res/drawable/ic_lock_power_off.xml
index 718f17e..babd1be 100644
--- a/core/res/res/drawable/ic_lock_power_off.xml
+++ b/core/res/res/drawable/ic_lock_power_off.xml
@@ -1,19 +1,25 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+    Copyright (C) 2016 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
+    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
+         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.
+    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.
 -->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_lock_power_off_alpha"
-    android:tint="?attr/colorControlNormal" />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M13.0,3.0l-2.0,0.0l0.0,10.0l2.0,0.0L13.0,3.0zm4.83,2.17l-1.42,1.42C17.99,7.86 19.0,9.81 19.0,12.0c0.0,3.87 -3.13,7.0 -7.0,7.0s-7.0,-3.13 -7.0,-7.0c0.0,-2.19 1.01,-4.14 2.58,-5.42L6.17,5.17C4.23,6.82 3.0,9.26 3.0,12.0c0.0,4.97 4.03,9.0 9.0,9.0s9.0,-4.03 9.0,-9.0c0.0,-2.74 -1.23,-5.18 -3.17,-6.83z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_restart.xml b/core/res/res/drawable/ic_restart.xml
new file mode 100644
index 0000000..47ac483
--- /dev/null
+++ b/core/res/res/drawable/ic_restart.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12.0,4.0L12.0,1.0L8.0,5.0l4.0,4.0L12.0,6.0c3.9,0.0 7.0,3.1 7.0,7.0c0.0,3.9 -3.1,7.0 -7.0,7.0l0.0,2.0c5.0,0.0 9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M5.0,12.9C5.0,11.0 5.8,9.2 7.2,7.9L5.8,6.4C4.0,8.1 3.0,10.5 3.0,12.9c0.0,4.0 2.7,7.6 6.5,8.7l0.5,-1.9C7.1,18.8 5.0,16.1 5.0,12.9z"/>
+</vector>
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index d12c8ba..d8dd447 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -41,7 +41,7 @@
                   android:visibility="gone"
                   style="?attr/borderlessButtonStyle"
                   android:textAppearance="?attr/textAppearanceButton"
-                  android:textColor="@color/material_deep_teal_500"
+                  android:textColor="?attr/colorAccent"
                   android:gravity="center_vertical"
                   android:layout_alignParentTop="true"
                   android:layout_alignParentRight="true"
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index ae94503..c4e8e9c 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -42,7 +42,7 @@
             android:visibility="gone"
             style="?attr/borderlessButtonStyle"
             android:textAppearance="?attr/textAppearanceButton"
-            android:textColor="@color/material_deep_teal_500"
+            android:textColor="?attr/colorAccent"
             android:gravity="center_vertical"
             android:layout_alignParentTop="true"
             android:layout_alignParentRight="true"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d15b175..6161494 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -539,9 +539,12 @@
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
 
-    <!-- Fast brightness animation ramp rate -->
+    <!-- Fast brightness animation ramp rate in brightness units per second-->
     <integer translatable="false" name="config_brightness_ramp_rate_fast">200</integer>
 
+    <!-- Slow brightness animation ramp rate in brightness units per second-->
+    <integer translatable="false" name="config_brightness_ramp_rate_slow">40</integer>
+
     <!-- Don't name config resources like this.  It should look like config_annoyDianne -->
     <bool name="config_annoy_dianne">true</bool>
 
@@ -2088,9 +2091,11 @@
          "bugreport" = Take bug report, if available
          "silent" = silent mode
          "users" = list of users
+         "restart" = restart device
          -->
     <string-array translatable="false" name="config_globalActionsList">
         <item>power</item>
+        <item>restart</item>
         <item>bugreport</item>
         <item>users</item>
     </string-array>
@@ -2517,6 +2522,10 @@
     <!-- Flag indicating whether round icons should be parsed from the application manifest. -->
     <bool name="config_useRoundIcon">false</bool>
 
+    <!-- Flag indicating whether the assist disclosure can be disabled using
+         ASSIST_DISCLOSURE_ENABLED. -->
+    <bool name="config_allowDisablingAssistDisclosure">false</bool>
+
     <!-- True if the device supports system navigation keys. -->
     <bool name="config_supportSystemNavigationKeys">false</bool>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5a9099b..c4594e5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -484,6 +484,10 @@
     <!-- label for item that turns off power in phone options dialog -->
     <string name="global_action_power_off">Power off</string>
 
+    <!-- label for item that restarts phone in phone options dialog -->
+    <!-- TODO: promote to separate string-->
+    <string name="global_action_restart" translatable="false">@string/sim_restart_button</string>
+
     <!-- label for item that generates a bug report in the phone options dialog -->
     <string name="global_action_bug_report">Bug report</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 384e9850..3c2b55b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1593,6 +1593,7 @@
   <java-symbol type="string" name="bugreport_title" />
   <java-symbol type="string" name="faceunlock_multiple_failures" />
   <java-symbol type="string" name="global_action_power_off" />
+  <java-symbol type="string" name="global_action_restart" />
   <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
   <java-symbol type="string" name="global_actions_airplane_mode_on_status" />
   <java-symbol type="string" name="global_actions_toggle_airplane_mode" />
@@ -1760,6 +1761,7 @@
   <java-symbol type="integer" name="config_undockedHdmiRotation" />
   <java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
   <java-symbol type="integer" name="config_brightness_ramp_rate_fast" />
+  <java-symbol type="integer" name="config_brightness_ramp_rate_slow" />
   <java-symbol type="layout" name="am_compat_mode_dialog" />
   <java-symbol type="layout" name="launch_warning" />
   <java-symbol type="layout" name="safe_mode" />
@@ -2682,6 +2684,7 @@
   <java-symbol type="drawable" name="ic_doc_generic" />
 
   <java-symbol type="bool" name="config_nightDisplayAvailable" />
+  <java-symbol type="bool" name="config_allowDisablingAssistDisclosure" />
   <java-symbol type="integer" name="config_defaultNightDisplayAutoMode" />
   <java-symbol type="integer" name="config_defaultNightDisplayCustomStartTime" />
   <java-symbol type="integer" name="config_defaultNightDisplayCustomEndTime" />
@@ -2691,4 +2694,7 @@
 
   <java-symbol type="bool" name="config_permissionReviewRequired" />
 
+
+  <java-symbol type="drawable" name="ic_restart" />
+
 </resources>
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 5221499..3ccbf17 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -29,6 +29,7 @@
  * TextViewTest tests {@link TextView}.
  */
 public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
+    private TextView mTextView;
 
     public TextViewTest() {
         super(TextViewActivity.class);
@@ -37,16 +38,22 @@
     @SmallTest
     @Presubmit
     public void testArray() throws Exception {
-        TextView tv = new TextView(getActivity());
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTextView = new TextView(getActivity());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
 
         char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
                                 'W', 'o', 'r', 'l', 'd', '!' };
 
-        tv.setText(c, 1, 4);
-        CharSequence oldText = tv.getText();
+        mTextView.setText(c, 1, 4);
+        CharSequence oldText = mTextView.getText();
 
-        tv.setText(c, 4, 5);
-        CharSequence newText = tv.getText();
+        mTextView.setText(c, 4, 5);
+        CharSequence newText = mTextView.getText();
 
         assertTrue(newText == oldText);
 
@@ -67,12 +74,18 @@
 
     @SmallTest
     public void testProcessTextActivityResultNonEditable() {
-        final TextView tv = new TextView(getActivity());
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTextView = new TextView(getActivity());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         CharSequence originalText = "This is some text.";
-        tv.setText(originalText, TextView.BufferType.SPANNABLE);
-        assertEquals(originalText, tv.getText().toString());
-        tv.setTextIsSelectable(true);
-        Selection.setSelection((Spannable) tv.getText(), 0, tv.getText().length());
+        mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+        assertEquals(originalText, mTextView.getText().toString());
+        mTextView.setTextIsSelectable(true);
+        Selection.setSelection((Spannable) mTextView.getText(), 0, mTextView.getText().length());
 
         // We need to run this in the UI thread, as it will create a Toast.
         getActivity().runOnUiThread(new Runnable() {
@@ -81,60 +94,79 @@
                 CharSequence newText = "Text is replaced.";
                 Intent data = new Intent();
                 data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
-                tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+                mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
             }
         });
         getInstrumentation().waitForIdleSync();
 
         // This is a TextView, which can't be modified. Hence no change should have been made.
-        assertEquals(originalText, tv.getText().toString());
+        assertEquals(originalText, mTextView.getText().toString());
     }
 
     @SmallTest
     public void testProcessTextActivityResultEditable() {
-        EditText tv = new EditText(getActivity());
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTextView = new EditText(getActivity());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         CharSequence originalText = "This is some text.";
-        tv.setText(originalText, TextView.BufferType.SPANNABLE);
-        assertEquals(originalText, tv.getText().toString());
-        tv.setTextIsSelectable(true);
-        Selection.setSelection(tv.getText(), 0, tv.getText().length());
+        mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+        assertEquals(originalText, mTextView.getText().toString());
+        mTextView.setTextIsSelectable(true);
+        Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
 
         CharSequence newText = "Text is replaced.";
         Intent data = new Intent();
         data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
-        tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+        mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
 
-        assertEquals(newText, tv.getText().toString());
+        assertEquals(newText, mTextView.getText().toString());
     }
 
     @SmallTest
     public void testProcessTextActivityResultCancel() {
-        EditText tv = new EditText(getActivity());
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTextView = new EditText(getActivity());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         CharSequence originalText = "This is some text.";
-        tv.setText(originalText, TextView.BufferType.SPANNABLE);
-        assertEquals(originalText, tv.getText().toString());
-        tv.setTextIsSelectable(true);
-        Selection.setSelection(tv.getText(), 0, tv.getText().length());
+        mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+        assertEquals(originalText, mTextView.getText().toString());
+        mTextView.setTextIsSelectable(true);
+        Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
 
         CharSequence newText = "Text is replaced.";
         Intent data = new Intent();
         data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
-        tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, data);
+        mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED,
+                data);
 
-        assertEquals(originalText, tv.getText().toString());
+        assertEquals(originalText, mTextView.getText().toString());
     }
 
     @SmallTest
     public void testProcessTextActivityNoData() {
-        EditText tv = new EditText(getActivity());
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTextView = new EditText(getActivity());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         CharSequence originalText = "This is some text.";
-        tv.setText(originalText, TextView.BufferType.SPANNABLE);
-        assertEquals(originalText, tv.getText().toString());
-        tv.setTextIsSelectable(true);
-        Selection.setSelection(tv.getText(), 0, tv.getText().length());
+        mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
+        assertEquals(originalText, mTextView.getText().toString());
+        mTextView.setTextIsSelectable(true);
+        Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
 
-        tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null);
+        mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null);
 
-        assertEquals(originalText, tv.getText().toString());
+        assertEquals(originalText, mTextView.getText().toString());
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
index ce6879d..b4afdda 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
@@ -178,19 +178,40 @@
                 clocks.elapsedRealtime() * 1000);
         offBatterySummaryParcel.setDataPosition(0);
 
-        // Read the on battery summary from the parcel.
-        BatteryStatsImpl.SamplingTimer unparceledTimer = new BatteryStatsImpl.SamplingTimer(
-                clocks, timeBase);
-        unparceledTimer.readSummaryFromParcelLocked(onBatterySummaryParcel);
+        // Set the timebase running again. That way any issues with tracking reported values
+        // get tested when we unparcel the timers below.
+        timeBase.setRunning(true, clocks.uptimeMillis(), clocks.elapsedRealtime());
 
-        assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        // Read the on battery summary from the parcel.
+        BatteryStatsImpl.SamplingTimer unparceledOnBatteryTimer =
+                new BatteryStatsImpl.SamplingTimer(clocks, timeBase);
+        unparceledOnBatteryTimer.readSummaryFromParcelLocked(onBatterySummaryParcel);
+
+        assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0,
+                BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
 
         // Read the off battery summary from the parcel.
-        unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase);
-        unparceledTimer.readSummaryFromParcelLocked(offBatterySummaryParcel);
+        BatteryStatsImpl.SamplingTimer unparceledOffBatteryTimer =
+                new BatteryStatsImpl.SamplingTimer(clocks, timeBase);
+        unparceledOffBatteryTimer.readSummaryFromParcelLocked(offBatterySummaryParcel);
 
-        assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED));
-        assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0,
+                BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, unparceledOffBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+        // Now, just like with a fresh timer, the first update should be absorbed to account for
+        // data being collected when we weren't recording.
+        unparceledOnBatteryTimer.update(10, 10);
+
+        assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0,
+                BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+        unparceledOffBatteryTimer.update(10, 10);
+
+        assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0,
+                BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, unparceledOffBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
     }
 }
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index fe68654..13880ec 100755
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -16,6 +16,13 @@
         </ol>
       </li>
       <li><a href="#using-rs-from-java">Using RenderScript from Java Code</a></li>
+      <li><a href="#reduction-in-depth">Reduction Kernels in Depth</a>
+        <ol>
+          <li><a href="#writing-reduction-kernel">Writing a reduction kernel</a></li>
+          <li><a href="#calling-reduction-kernel">Calling a reduction kernel from Java code</a></li>
+          <li><a href="#more-example">More example reduction kernels</a></li>
+        </ol>
+      </li>
     </ol>
 
     <h2>Related Samples</h2>
@@ -29,16 +36,18 @@
 
 <p>RenderScript is a framework for running computationally intensive tasks at high performance on
 Android. RenderScript is primarily oriented for use with data-parallel computation, although serial
-computationally intensive workloads can benefit as well. The RenderScript runtime will parallelize
-work across all processors available on a device, such as multi-core CPUs, GPUs, or DSPs, allowing
-you to focus on expressing algorithms rather than scheduling work or load balancing. RenderScript is
+workloads can benefit as well. The RenderScript runtime parallelizes
+work across processors available on a device, such as multi-core CPUs and GPUs. This allows
+you to focus on expressing algorithms rather than scheduling work. RenderScript is
 especially useful for applications performing image processing, computational photography, or
 computer vision.</p>
 
 <p>To begin with RenderScript, there are two main concepts you should understand:</p>
 <ul>
 
-<li>High-performance compute kernels are written in a C99-derived language.</li>
+<li>High-performance compute kernels are written in a C99-derived language. A <i>compute
+    kernel</i> is a function or collection of functions that you can direct the RenderScript runtime
+    to execute in parallel across a collection of data.</li>
 
 <li>A Java API is used for managing the lifetime of RenderScript resources and controlling kernel
 execution.</li>
@@ -48,7 +57,7 @@
 
 <p>A RenderScript kernel typically resides in a <code>.rs</code> file in the
 <code>&lt;project_root&gt;/src/</code> directory; each <code>.rs</code> file is called a
-script. Every script contains its own set of kernels, functions, and variables. A script can
+<i>script</i>. Every script contains its own set of kernels, functions, and variables. A script can
 contain:</p>
 
 <ul>
@@ -57,23 +66,32 @@
 
 <li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
 declares the package name of the Java classes reflected from this script.
-Note that your .rs file must be part of your application package, and not in a
+Note that your <code>.rs</code> file must be part of your application package, and not in a
 library project.</li>
 
-<li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
+<li>Zero or more <strong><i>invokable functions</i></strong>. An invokable function is a single-threaded RenderScript
 function that you can call from your Java code with arbitrary arguments. These are often useful for
 initial setup or serial computations within a larger processing pipeline.</li>
 
-<li>Some number of script globals. A script global is equivalent to a global variable in C. You can
+<li><p>Zero or more <strong><i>script globals</i></strong>. A script global is equivalent to a global variable in C. You can
 access script globals from Java code, and these are often used for parameter passing to RenderScript
-kernels.</li>
+kernels.</p></li>
 
-<li>Some number of compute kernels. A kernel is a parallel function that executes across every
-{@link android.renderscript.Element} within an {@link android.renderscript.Allocation}.
+<li><p>Zero or more <strong><i>compute kernels</i></strong>. There are two kinds of compute
+kernels: <i>mapping</i> kernels (also called <i>foreach</i> kernels)
+and <i>reduction</i> kernels.</p>
 
-<p>A simple kernel may look like the following:</p>
+<p>A <em>mapping kernel</em> is a parallel function that operates on a collection of {@link
+  android.renderscript.Allocation Allocations} of the same dimensions. By default, it executes
+  once for every coordinate in those dimensions. It is typically (but not exclusively) used to
+  transform a collection of input {@link android.renderscript.Allocation Allocations} to an
+  output {@link android.renderscript.Allocation} one {@link android.renderscript.Element} at a
+  time.</p>
 
-<pre>uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {
+<ul>
+<li><p>Here is an example of a simple <strong>mapping kernel</strong>:</p>
+
+<pre>uchar4 RS_KERNEL invert(uchar4 in, uint32_t x, uint32_t y) {
   uchar4 out = in;
   out.r = 255 - in.r;
   out.g = 255 - in.g;
@@ -81,40 +99,113 @@
   return out;
 }</pre>
 
-<p>In most respects, this is identical to a standard C function. The first notable feature is the
-<code>__attribute__((kernel))</code> applied to the function prototype. This denotes that the
-function is a RenderScript kernel instead of an invokable function. The next feature is the
-<code>in</code> argument and its type. In a RenderScript kernel, this is a special argument that is
-automatically filled in based on the input {@link android.renderscript.Allocation} passed to the
-kernel launch. By default, the kernel is run across an entire {@link
-android.renderscript.Allocation}, with one execution of the kernel body per {@link
-android.renderscript.Element} in the {@link android.renderscript.Allocation}. The third notable
-feature is the return type of the kernel. The value returned from the kernel is automatically
-written to the appropriate location in the output {@link android.renderscript.Allocation}. The
-RenderScript runtime checks to ensure that the {@link android.renderscript.Element} types of the
-input and output Allocations match the kernel's prototype; if they do not match, an exception is
-thrown.</p>
+<p>In most respects, this is identical to a standard C
+  function. The <a href="#RS_KERNEL"><code>RS_KERNEL</code></a> property applied to the
+  function prototype specifies that the function is a RenderScript mapping kernel instead of an
+  invokable function. The <code>in</code> argument is automatically filled in based on the
+  input {@link android.renderscript.Allocation} passed to the kernel launch. The
+  arguments <code>x</code> and <code>y</code> are
+  discussed <a href="#special-arguments">below</a>. The value returned from the kernel is
+  automatically written to the appropriate location in the output {@link
+  android.renderscript.Allocation}. By default, this kernel is run across its entire input
+  {@link android.renderscript.Allocation}, with one execution of the kernel function per {@link
+  android.renderscript.Element} in the {@link android.renderscript.Allocation}.</p>
 
-<p>A kernel may have an input {@link android.renderscript.Allocation}, an output {@link
-android.renderscript.Allocation}, or both. A kernel may not have more than one input or one output
-{@link android.renderscript.Allocation}. If more than one input or output is required, those objects
-should be bound to <code>rs_allocation</code> script globals and accessed from a kernel or invokable
-function via <code>rsGetElementAt_<em>type</em>()</code> or
-<code>rsSetElementAt_<em>type</em>()</code>.</p>
+<p>A mapping kernel may have one or more input {@link android.renderscript.Allocation
+  Allocations}, a single output {@link android.renderscript.Allocation}, or both. The
+  RenderScript runtime checks to ensure that all input and output Allocations have the same
+  dimensions, and that the {@link android.renderscript.Element} types of the input and output
+  Allocations match the kernel's prototype; if either of these checks fails, RenderScript
+  throws an exception.</p>
 
-<p>A kernel may access the coordinates of the current execution using the <code>x</code>,
-<code>y</code>, and <code>z</code> arguments. These arguments are optional, but the type of the
-coordinate arguments must be <code>uint32_t</code>.</p></li>
+<p class="note"><strong>NOTE:</strong> Before Android 6.0 (API level 23), a mapping kernel may
+  not have more than one input {@link android.renderscript.Allocation}.</p>
+
+<p>If you need more input or output {@link android.renderscript.Allocation Allocations} than
+  the kernel has, those objects should be bound to <code>rs_allocation</code> script globals
+  and accessed from a kernel or invokable function
+  via <code>rsGetElementAt_<i>type</i>()</code> or <code>rsSetElementAt_<i>type</i>()</code>.</p>
+
+<p><strong>NOTE:</strong> <a id="RS_KERNEL"><code>RS_KERNEL</code></a> is a macro
+  defined automatically by RenderScript for your convenience:</p>
+<pre>
+#define RS_KERNEL __attribute__((kernel))
+</pre>
+</li>
+</ul>
+
+<p>A <em>reduction kernel</em> is a family of functions that operates on a collection of input
+  {@link android.renderscript.Allocation Allocations} of the same dimensions. By default,
+  its <a href="#accumulator-function">accumulator function</a> executes once for every
+  coordinate in those dimensions.  It is typically (but not exclusively) used to "reduce" a
+  collection of input {@link android.renderscript.Allocation Allocations} to a single
+  value.</p>
+
+<ul>
+<li><p>Here is an <a id="example-addint">example</a> of a simple <strong>reduction
+kernel</strong> that adds up the {@link android.renderscript.Element Elements} of its
+input:</p>
+
+<pre>#pragma rs reduce(addint) accumulator(addintAccum)
+
+static void addintAccum(int *accum, int val) {
+  *accum += val;
+}</pre>
+
+<p>A reduction kernel consists of one or more user-written functions.
+<code>#pragma rs reduce</code> is used to define the kernel by specifying its name
+(<code>addint</code>, in this example) and the names and roles of the functions that make
+up the kernel (an <code>accumulator</code> function <code>addintAccum</code>, in this
+example). All such functions must be <code>static</code>. A reduction kernel always
+requires an <code>accumulator</code> function; it may also have other functions, depending
+on what you want the kernel to do.</p>
+
+<p>A reduction kernel accumulator function must return <code>void</code> and must have at least
+two arguments. The first argument (<code>accum</code>, in this example) is a pointer to
+an <i>accumulator data item</i> and the second (<code>val</code>, in this example) is
+automatically filled in based on the input {@link android.renderscript.Allocation} passed to
+the kernel launch. The accumulator data item is created by the RenderScript runtime; by
+default, it is initialized to zero. By default, this kernel is run across its entire input
+{@link android.renderscript.Allocation}, with one execution of the accumulator function per
+{@link android.renderscript.Element} in the {@link android.renderscript.Allocation}. By
+default, the final value of the accumulator data item is treated as the result of the
+reduction, and is returned to Java.  The RenderScript runtime checks to ensure that the {@link
+android.renderscript.Element} type of the input Allocation matches the accumulator function's
+prototype; if it does not match, RenderScript throws an exception.</p>
+
+<p>A reduction kernel has one or more input {@link android.renderscript.Allocation
+Allocations} but no output {@link android.renderscript.Allocation Allocations}.</p></li>
+
+<p>Reduction kernels are explained in more detail <a href="#reduction-in-depth">here</a>.</p>
+
+<p>Reduction kernels are supported in Android 7.0 (API level 24) and later.</p>
+</li>
+</ul>
+
+<p>A mapping kernel function or a reduction kernel accumulator function may access the coordinates
+of the current execution using the <a id="special-arguments">special arguments</a> <code>x</code>,
+<code>y</code>, and <code>z</code>, which must be of type <code>int</code> or <code>uint32_t</code>.
+These arguments are optional.</p>
+
+<p>A mapping kernel function or a reduction kernel accumulator
+function may also take the optional special argument
+<code>context</code> of type <a
+href='reference/rs_for_each.html#android_rs:rs_kernel_context'>rs_kernel_context</a>.
+It is needed by a family of runtime APIs that are used to query
+certain properties of the current execution -- for example, <a
+href='reference/rs_for_each.html#android_rs:rsGetDimX'>rsGetDimX</a>.
+(The <code>context</code> argument is available in Android 6.0 (API level 23) and later.)</p>
+</li>
 
 <li>An optional <code>init()</code> function. An <code>init()</code> function is a special type of
-invokable function that is run when the script is first instantiated. This allows for some
+invokable function that RenderScript runs when the script is first instantiated. This allows for some
 computation to occur automatically at script creation.</li>
 
-<li>Some number of static script globals and functions. A static script global is equivalent to a
-script global except that it cannot be set from Java code. A static function is a standard C
+<li>Zero or more <strong><i>static script globals and functions</i></strong>. A static script global is equivalent to a
+script global except that it cannot be accessed from Java code. A static function is a standard C
 function that can be called from any kernel or invokable function in the script but is not exposed
 to the Java API. If a script global or function does not need to be called from Java code, it is
-highly recommended that those be declared <code>static</code>.</li> </ul>
+highly recommended that it be declared <code>static</code>.</li> </ul>
 
 <h4>Setting floating point precision</h4>
 
@@ -129,13 +220,13 @@
 
 </li>
 
-  <li><code>#pragma rs_fp_relaxed</code> - For apps that don’t require strict IEEE 754-2008
+  <li><code>#pragma rs_fp_relaxed</code>: For apps that don’t require strict IEEE 754-2008
     compliance and can tolerate less precision. This mode enables flush-to-zero for denorms and
     round-towards-zero.
 
 </li>
 
-  <li><code>#pragma rs_fp_imprecise</code> - For apps that don’t have stringent precision
+  <li><code>#pragma rs_fp_imprecise</code>: For apps that don’t have stringent precision
     requirements. This mode enables everything in <code>rs_fp_relaxed</code> along with the
     following:
 
@@ -162,14 +253,21 @@
     available on devices running Android 3.0 (API level 11) and higher. </li>
   <li><strong>{@link android.support.v8.renderscript}</strong> - The APIs in this package are
     available through a <a href="{@docRoot}tools/support-library/features.html#v8">Support
-    Library</a>, which allows you to use them on devices running Android 2.2 (API level 8) and
+    Library</a>, which allows you to use them on devices running Android 2.3 (API level 9) and
     higher.</li>
 </ul>
 
-<p>We strongly recommend using the Support Library APIs for accessing RenderScript because they
-  provide a wider range of device compatibility. Developers targeting specific versions of
-  Android can use {@link android.renderscript} if necessary.</p>
+<p>Here are the tradeoffs:</p>
 
+<ul>
+<li>If you use the Support Library APIs, the RenderScript portion of your application will be
+  compatible with devices running Android 2.3 (API level 9) and higher, regardless of which RenderScript
+  features you use. This allows your application to work on more devices than if you use the
+  native (<strong>{@link android.renderscript}</strong>) APIs.</li>
+<li>Certain RenderScript features are not available through the Support Library APIs.</li>
+<li>If you use the Support Library APIs, you will get (possibly significantly) larger APKs than
+if you use the native (<strong>{@link android.renderscript}</strong>) APIs.</li>
+</ul>
 
 <h3 id="ide-setup">Using the RenderScript Support Library APIs</h3>
 
@@ -202,7 +300,7 @@
     buildToolsVersion "23.0.3"
 
     defaultConfig {
-        minSdkVersion 8
+        minSdkVersion 9
         targetSdkVersion 19
 <strong>
         renderscriptTargetApi 18
@@ -250,7 +348,7 @@
 
 <p>Using RenderScript from Java code relies on the API classes located in the
 {@link android.renderscript} or the {@link android.support.v8.renderscript} package. Most
-applications follow the same basic usage patterns:</p>
+applications follow the same basic usage pattern:</p>
 
 <ol>
 
@@ -266,12 +364,12 @@
 script.</strong> An {@link android.renderscript.Allocation} is a RenderScript object that provides
 storage for a fixed amount of data. Kernels in scripts take {@link android.renderscript.Allocation}
 objects as their input and output, and {@link android.renderscript.Allocation} objects can be
-accessed in kernels using <code>rsGetElementAt_<em>type</em>()</code> and
-<code>rsSetElementAt_<em>type</em>()</code> when bound as script globals. {@link
+accessed in kernels using <code>rsGetElementAt_<i>type</i>()</code> and
+<code>rsSetElementAt_<i>type</i>()</code> when bound as script globals. {@link
 android.renderscript.Allocation} objects allow arrays to be passed from Java code to RenderScript
 code and vice-versa. {@link android.renderscript.Allocation} objects are typically created using
-{@link android.renderscript.Allocation#createTyped} or {@link
-android.renderscript.Allocation#createFromBitmap}.</li>
+{@link android.renderscript.Allocation#createTyped createTyped()} or {@link
+android.renderscript.Allocation#createFromBitmap createFromBitmap()}.</li>
 
 <li><strong>Create whatever scripts are necessary.</strong> There are two types of scripts available
 to you when using RenderScript:
@@ -281,9 +379,9 @@
 <li><strong>ScriptC</strong>: These are the user-defined scripts as described in <a
 href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> above. Every script has a Java class
 reflected by the RenderScript compiler in order to make it easy to access the script from Java code;
-this class will have the name <code>ScriptC_<em>filename</em></code>. For example, if the kernel
-above was located in <code>invert.rs</code> and a RenderScript context was already located in
-<code>mRS</code>, the Java code to instantiate the script would be:
+this class has the name <code>ScriptC_<i>filename</i></code>. For example, if the mapping kernel
+above were located in <code>invert.rs</code> and a RenderScript context were already located in
+<code>mRenderScript</code>, the Java code to instantiate the script would be:
 
 <pre>ScriptC_invert invert = new ScriptC_invert(mRenderScript);</pre></li>
 
@@ -294,35 +392,926 @@
 </ul></li>
 
 <li><strong>Populate Allocations with data.</strong> Except for Allocations created with {@link
-android.renderscript.Allocation#createFromBitmap}, an Allocation will be populated with empty data when it is
-first created. To populate an Allocation, use one of the <code>copy</code> methods in {@link
-android.renderscript.Allocation}.</li>
+android.renderscript.Allocation#createFromBitmap createFromBitmap()}, an Allocation is populated with empty data when it is
+first created. To populate an Allocation, use one of the "copy" methods in {@link
+android.renderscript.Allocation}. The "copy" methods are <a href="#asynchronous-model">synchronous</a>.</li>
 
-<li><strong>Set any necessary script globals.</strong> Globals may be set using methods in the same
-<code>ScriptC_<em>filename</em></code> class with methods named
-<code>set_<em>globalname</em></code>. For example, in order to set an <code>int</code> named
-<code>elements</code>, use the Java method <code>set_elements(int)</code>. RenderScript objects can
-also be set in kernels; for example, the <code>rs_allocation</code> variable named
-<code>lookup</code> can be set with the method <code>set_lookup(Allocation)</code>.</li>
+<li><strong>Set any necessary script globals.</strong> You may set globals using methods in the
+  same <code>ScriptC_<i>filename</i></code> class named <code>set_<i>globalname</i></code>. For
+  example, in order to set an <code>int</code> variable named <code>threshold</code>, use the
+  Java method <code>set_threshold(int)</code>; and in order to set
+  an <code>rs_allocation</code> variable named <code>lookup</code>, use the Java
+  method <code>set_lookup(Allocation)</code>. The <code>set</code> methods
+  are <a href="#asynchronous-model">asynchronous</a>.</li>
 
-<li><strong>Launch the appropriate kernels.</strong> Methods to launch a given kernel will be
-reflected in the same <code>ScriptC_<em>filename</em></code> class with methods named
-<code>forEach_<em>kernelname</em>()</code>. These launches are asynchronous, and launches will be
-serialized in the order in which they are launched. Depending on the arguments to the kernel, the
-method will take either one or two Allocations. By default, a kernel will execute over the entire
-input or output Allocation; to execute over a subset of that Allocation, pass an appropriate {@link
-android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> method.
+<li><strong>Launch the appropriate kernels and invokable functions.</strong>
+<p>Methods to launch a given kernel are
+reflected in the same <code>ScriptC_<i>filename</i></code> class with methods named
+<code>forEach_<i>mappingKernelName</i>()</code>
+or <code>reduce_<i>reductionKernelName</i>()</code>.
+These launches are <a href="#asynchronous-model">asynchronous</a>.
+Depending on the arguments to the kernel, the
+method takes one or more Allocations, all of which must have the same dimensions. By default, a
+kernel executes over every coordinate in those dimensions; to execute a kernel over a subset of those coordinates,
+pass an appropriate {@link
+android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> or <code>reduce</code> method.</p>
 
-<p>Invoked functions can be launched using the <code>invoke_<em>functionname</em></code> methods
-reflected in the same <code>ScriptC_<em>filename</em></code> class.</p></li>
+<p>Launch invokable functions using the <code>invoke_<i>functionName</i></code> methods
+reflected in the same <code>ScriptC_<i>filename</i></code> class.
+These launches are <a href="#asynchronous-model">asynchronous</a>.</p></li>
 
-<li><strong>Copy data out of {@link android.renderscript.Allocation} objects.</strong> In order to
-access data from an {@link android.renderscript.Allocation} from Java code, that data must be copied
-back to Java buffers using one of the <code>copy</code> methods in {@link
-android.renderscript.Allocation}. These functions will synchronize with asynchronous kernel and
-function launches as necessary.</li>
+<li><strong>Retrieve data from {@link android.renderscript.Allocation} objects
+and <i><a href="#javaFutureType">javaFutureType</a></i> objects.</strong>
+In order to
+access data from an {@link android.renderscript.Allocation} from Java code, you must copy that data
+back to Java using one of the "copy" methods in {@link
+android.renderscript.Allocation}.
+In order to obtain the result of a reduction kernel, you must use the <code><i>javaFutureType</i>.get()</code> method.
+The "copy" and <code>get()</code> methods are <a href="#asynchronous-model">synchronous</a>.</li>
 
-<li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
+<li><strong>Tear down the RenderScript context.</strong> You can destroy the RenderScript context
 with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
-object to be garbage collected. This will cause any further use of any object belonging to that
+object to be garbage collected. This causes any further use of any object belonging to that
 context to throw an exception.</li> </ol>
+
+<h3 id="asynchronous-model">Asynchronous execution model</h3>
+
+<p>The reflected <code>forEach</code>, <code>invoke</code>, <code>reduce</code>,
+  and <code>set</code> methods are asynchronous -- each may return to Java before completing the
+  requested action.  However, the individual actions are serialized in the order in which they are launched.</p>
+
+<p>The {@link android.renderscript.Allocation} class provides "copy" methods to copy data to
+  and from Allocations.  A "copy" method is synchronous, and is serialized with respect to any
+  of the asynchronous actions above that touch the same Allocation.</p>
+
+<p>The reflected <i><a href="#javaFutureType">javaFutureType</a></i> classes provide
+  a <code>get()</code> method to obtain the result of a reduction. <code>get()</code> is
+  synchronous, and is serialized with respect to the reduction (which is asynchronous).</p>
+
+<h2 id="reduction-in-depth">Reduction Kernels in Depth</h2>
+
+<p><i>Reduction</i> is the process of combining a collection of data into a single
+value. This is a useful primitive in parallel programming, with applications such as the
+following:</p>
+<ul>
+  <li>computing the sum or product over all the data</li>
+  <li>computing logical operations (<code>and</code>, <code>or</code>, <code>xor</code>)
+  over all the data</li>
+  <li>finding the minimum or maximum value within the data</li>
+  <li>searching for a specific value or for the coordinate of a specific value within the data</li>
+</ul>
+
+<p>In Android 7.0 (API level 24) and later, RenderScript supports <i>reduction kernels</i> to allow
+efficient user-written reduction algorithms. You may launch reduction kernels on inputs with
+1, 2, or 3 dimensions.<p>
+
+<p>An example above shows a simple <a href="#example-addint">addint</a> reduction kernel.
+Here is a more complicated <a id="example-findMinAndMax">findMinAndMax</a> reduction kernel
+that finds the locations of the minimum and maximum <code>long</code> values in a
+1-dimensional {@link android.renderscript.Allocation}:</p>
+
+<pre>
+#define LONG_MAX (long)((1UL << 63) - 1)
+#define LONG_MIN (long)(1UL << 63)
+
+#pragma rs reduce(findMinAndMax) \
+  initializer(fMMInit) accumulator(fMMAccumulator) \
+  combiner(fMMCombiner) outconverter(fMMOutConverter)
+
+// Either a value and the location where it was found, or <a href="#INITVAL">INITVAL</a>.
+typedef struct {
+  long val;
+  int idx;     // -1 indicates <a href="#INITVAL">INITVAL</a>
+} IndexedVal;
+
+typedef struct {
+  IndexedVal min, max;
+} MinAndMax;
+
+// In discussion below, this initial value { { LONG_MAX, -1 }, { LONG_MIN, -1 } }
+// is called <a id="INITVAL">INITVAL</a>.
+static void fMMInit(MinAndMax *accum) {
+  accum->min.val = LONG_MAX;
+  accum->min.idx = -1;
+  accum->max.val = LONG_MIN;
+  accum->max.idx = -1;
+}
+
+//----------------------------------------------------------------------
+// In describing the behavior of the accumulator and combiner functions,
+// it is helpful to describe hypothetical functions
+//   IndexedVal min(IndexedVal a, IndexedVal b)
+//   IndexedVal max(IndexedVal a, IndexedVal b)
+//   MinAndMax  minmax(MinAndMax a, MinAndMax b)
+//   MinAndMax  minmax(MinAndMax accum, IndexedVal val)
+//
+// The effect of
+//   IndexedVal min(IndexedVal a, IndexedVal b)
+// is to return the IndexedVal from among the two arguments
+// whose val is lesser, except that when an IndexedVal
+// has a negative index, that IndexedVal is never less than
+// any other IndexedVal; therefore, if exactly one of the
+// two arguments has a negative index, the min is the other
+// argument. Like ordinary arithmetic min and max, this function
+// is commutative and associative; that is,
+//
+//   min(A, B) == min(B, A)               // commutative
+//   min(A, min(B, C)) == min((A, B), C)  // associative
+//
+// The effect of
+//   IndexedVal max(IndexedVal a, IndexedVal b)
+// is analogous (greater . . . never greater than).
+//
+// Then there is
+//
+//   MinAndMax minmax(MinAndMax a, MinAndMax b) {
+//     return MinAndMax(min(a.min, b.min), max(a.max, b.max));
+//   }
+//
+// Like ordinary arithmetic min and max, the above function
+// is commutative and associative; that is:
+//
+//   minmax(A, B) == minmax(B, A)                  // commutative
+//   minmax(A, minmax(B, C)) == minmax((A, B), C)  // associative
+//
+// Finally define
+//
+//   MinAndMax minmax(MinAndMax accum, IndexedVal val) {
+//     return minmax(accum, MinAndMax(val, val));
+//   }
+//----------------------------------------------------------------------
+
+// This function can be explained as doing:
+//   *accum = minmax(*accum, IndexedVal(in, x))
+//
+// This function simply computes minimum and maximum values as if
+// INITVAL.min were greater than any other minimum value and
+// INITVAL.max were less than any other maximum value.  Note that if
+// *accum is INITVAL, then this function sets
+//   *accum = IndexedVal(in, x)
+//
+// After this function is called, both accum->min.idx and accum->max.idx
+// will have nonnegative values:
+// - x is always nonnegative, so if this function ever sets one of the
+//   idx fields, it will set it to a nonnegative value
+// - if one of the idx fields is negative, then the corresponding
+//   val field must be LONG_MAX or LONG_MIN, so the function will always
+//   set both the val and idx fields
+static void fMMAccumulator(MinAndMax *accum, long in, int x) {
+  IndexedVal me;
+  me.val = in;
+  me.idx = x;
+
+  if (me.val <= accum->min.val)
+    accum->min = me;
+  if (me.val >= accum->max.val)
+    accum->max = me;
+}
+
+// This function can be explained as doing:
+//   *accum = minmax(*accum, *val)
+//
+// This function simply computes minimum and maximum values as if
+// INITVAL.min were greater than any other minimum value and
+// INITVAL.max were less than any other maximum value.  Note that if
+// one of the two accumulator data items is INITVAL, then this
+// function sets *accum to the other one.
+static void fMMCombiner(MinAndMax *accum,
+                        const MinAndMax *val) {
+  if ((accum->min.idx < 0) || (val->min.val < accum->min.val))
+    accum->min = val->min;
+  if ((accum->max.idx < 0) || (val->max.val > accum->max.val))
+    accum->max = val->max;
+}
+
+static void fMMOutConverter(int2 *result,
+                            const MinAndMax *val) {
+  result->x = val->min.idx;
+  result->y = val->max.idx;
+}
+</pre>
+
+<p class="note"><strong>NOTE:</strong> There are more example reduction
+  kernels <a href="#more-example">here</a>.</p>
+
+<p>In order to run a reduction kernel, the RenderScript runtime creates <em>one or more</em>
+variables called <a id="accumulator-data-items"><strong><i>accumulator data
+items</i></strong></a> to hold the state of the reduction process. The RenderScript runtime
+picks the number of accumulator data items in such a way as to maximize performance. The type
+of the accumulator data items (<i>accumType</i>) is determined by the kernel's <i>accumulator
+function</i> -- the first argument to that function is a pointer to an accumulator data
+item. By default, every accumulator data item is initialized to zero (as if
+by <code>memset</code>); however, you may write an <i>initializer function</i> to do something
+different.</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+kernel, the accumulator data items (of type <code>int</code>) are used to add up input
+values. There is no initializer function, so each accumulator data item is initialized to
+zero.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the accumulator data items
+(of type <code>MinAndMax</code>) are used to keep track of the minimum and maximum values
+found so far. There is an initializer function to set these to <code>LONG_MAX</code> and
+<code>LONG_MIN</code>, respectively; and to set the locations of these values to -1, indicating that
+the values are not actually present in the (empty) portion of the input that has been
+processed.</p>
+
+<p>RenderScript calls your accumulator function once for every coordinate in the
+input(s). Typically, your function should update the accumulator data item in some way
+according to the input.</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+kernel, the accumulator function adds the value of an input Element to the accumulator
+data item.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the accumulator function
+checks to see whether the value of an input Element is less than or equal to the minimum
+value recorded in the accumulator data item and/or greater than or equal to the maximum
+value recorded in the accumulator data item, and updates the accumulator data item
+accordingly.</p>
+
+<p>After the accumulator function has been called once for every coordinate in the input(s),
+RenderScript must <strong>combine</strong> the <a href="#accumulator-data-items">accumulator
+data items</a> together into a single accumulator data item. You may write a <i>combiner
+function</i> to do this. If the accumulator function has a single input and
+no <a href="#special-arguments">special arguments</a>, then you do not need to write a combiner
+function; RenderScript will use the accumulator function to combine the accumulator data
+items. (You may still write a combiner function if this default behavior is not what you
+want.)</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+kernel, there is no combiner function, so the accumulator function will be used. This is
+the correct behavior, because if we split a collection of values into two pieces, and we
+add up the values in those two pieces separately, adding up those two sums is the same as
+adding up the entire collection.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the combiner function
+checks to see whether the minimum value recorded in the "source" accumulator data
+item <code>*val</code> is less then the minimum value recorded in the "destination"
+accumulator data item <code>*accum</code>, and updates <code>*accum</code>
+accordingly. It does similar work for the maximum value. This updates <code>*accum</code>
+to the state it would have had if all of the input values had been accumulated into
+<code>*accum</code> rather than some into <code>*accum</code> and some into
+<code>*val</code>.</p>
+
+<p>After all of the accumulator data items have been combined, RenderScript determines
+the result of the reduction to return to Java. You may write an <i>outconverter
+function</i> to do this. You do not need to write an outconverter function if you want
+the final value of the combined accumulator data items to be the result of the reduction.</p>
+
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel,
+there is no outconverter function.  The final value of the combined data items is the sum of
+all Elements of the input, which is the value we want to return.</p>
+
+<p class="note"><strong>Example:</strong> In
+the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the outconverter function
+initializes an <code>int2</code> result value to hold the locations of the minimum and
+maximum values resulting from the combination of all of the accumulator data items.</p>
+
+<h3 id="writing-reduction-kernel">Writing a reduction kernel</h3>
+
+<p><code>#pragma rs reduce</code> defines a reduction kernel by
+specifying its name and the names and roles of the functions that make
+up the kernel.  All such functions must be
+<code>static</code>. A reduction kernel always requires an <code>accumulator</code>
+function; you can omit some or all of the other functions, depending on what you want the
+kernel to do.</p>
+
+<pre>#pragma rs reduce(<i>kernelName</i>) \
+  initializer(<i>initializerName</i>) \
+  accumulator(<i>accumulatorName</i>) \
+  combiner(<i>combinerName</i>) \
+  outconverter(<i>outconverterName</i>)
+</pre>
+
+<p>The meaning of the items in the <code>#pragma</code> is as follows:</p>
+<ul>
+
+<li><code>reduce(<i>kernelName</i>)</code> (mandatory): Specifies that a reduction kernel is
+being defined. A reflected Java method <code>reduce_<i>kernelName</i></code> will launch the
+kernel.</li>
+
+<li><p><code>initializer(<i>initializerName</i>)</code> (optional): Specifies the name of the
+initializer function for this reduction kernel. When you launch the kernel, RenderScript calls
+this function once for each <a href="#accumulator-data-items">accumulator data item</a>. The
+function must be defined like this:</p>
+
+<pre>static void <i>initializerName</i>(<i>accumType</i> *accum) { … }</pre>
+
+<p><code>accum</code> is a pointer to an accumulator data item for this function to
+initialize.</p>
+
+<p>If you do not provide an initializer function, RenderScript initializes every accumulator
+data item to zero (as if by <code>memset</code>), behaving as if there were an initializer
+function that looks like this:</p>
+<pre>static void <i>initializerName</i>(<i>accumType</i> *accum) {
+  memset(accum, 0, sizeof(*accum));
+}</pre>
+</li>
+
+<li><p><code><a id="accumulator-function">accumulator(<i>accumulatorName</i>)</a></code>
+(mandatory): Specifies the name of the accumulator function for this
+reduction kernel. When you launch the kernel, RenderScript calls
+this function once for every coordinate in the input(s), to update an
+accumulator data item in some way according to the input(s). The function
+must be defined like this:</p>
+
+<pre>
+static void <i>accumulatorName</i>(<i>accumType</i> *accum,
+                            <i>in1Type</i> in1, <i>&hellip;,</i> <i>inNType</i> in<i>N</i>
+                            <i>[, specialArguments]</i>) { &hellip; }
+</pre>
+
+<p><code>accum</code> is a pointer to an accumulator data item for this function to
+modify. <code>in1</code> through <code>in<i>N</i></code> are one <em>or more</em> arguments that
+are automatically filled in based on the inputs passed to the kernel launch, one argument
+per input. The accumulator function may optionally take any of the <a
+href="#special-arguments">special arguments</a>.</p>
+
+<p>An example kernel with multiple inputs is <a href="#dot-product"><code>dotProduct</code></a>.</p>
+</li>
+
+<li><code><a id="combiner-function">combiner(<i>combinerName</i>)</a></code>
+(optional): Specifies the name of the combiner function for this
+reduction kernel. After RenderScript calls the accumulator function
+once for every coordinate in the input(s), it calls this function as many
+times as necessary to combine all accumulator data items into a single
+accumulator data item. The function must be defined like this:</p>
+
+<pre>static void <i>combinerName</i>(<i>accumType</i> *accum, const <i>accumType</i> *other) { … }</pre>
+
+<p><code>accum</code> is a pointer to a "destination" accumulator data item for this
+function to modify. <code>other</code> is a pointer to a "source" accumulator data item
+for this function to "combine" into <code>*accum</code>.</p>
+
+<p class="note"><strong>NOTE:</strong> It is possible
+  that <code>*accum</code>, <code>*other</code>, or both have been initialized but have never
+  been passed to the accumulator function; that is, one or both have never been updated
+  according to any input data. For example, in
+  the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the combiner
+  function <code>fMMCombiner</code> explicitly checks for <code>idx &lt; 0</code> because that
+  indicates such an accumulator data item, whose value is <a href="#INITVAL">INITVAL</a>.</p>
+
+<p>If you do not provide a combiner function, RenderScript uses the accumulator function in its
+place, behaving as if there were a combiner function that looks like this:</p>
+
+<pre>static void <i>combinerName</i>(<i>accumType</i> *accum, const <i>accumType</i> *other) {
+  <i>accumulatorName</i>(accum, *other);
+}</pre>
+
+<p>A combiner function is mandatory if the kernel has more than one input, if the input data
+  type is not the same as the accumulator data type, or if the accumulator function takes one
+  or more <a href="#special-arguments">special arguments</a>.</p>
+</li>
+
+<li><p><code><a id="outconverter-function">outconverter(<i>outconverterName</i>)</a></code>
+(optional): Specifies the name of the outconverter function for this
+reduction kernel. After RenderScript combines all of the accumulator
+data items, it calls this function to determine the result of the
+reduction to return to Java. The function must be defined like
+this:</p>
+
+<pre>static void <i>outconverterName</i>(<i>resultType</i> *result, const <i>accumType</i> *accum) { … }</pre>
+
+<p><code>result</code> is a pointer to a result data item (allocated but not initialized
+by the RenderScript runtime) for this function to initialize with the result of the
+reduction. <i>resultType</i> is the type of that data item, which need not be the same
+as <i>accumType</i>. <code>accum</code> is a pointer to the final accumulator data item
+computed by the <a href="#combiner-function">combiner function</a>.</p>
+
+<p>If you do not provide an outconverter function, RenderScript copies the final accumulator
+data item to the result data item, behaving as if there were an outconverter function that
+looks like this:</p>
+
+<pre>static void <i>outconverterName</i>(<i>accumType</i> *result, const <i>accumType</i> *accum) {
+  *result = *accum;
+}</pre>
+
+<p>If you want a different result type than the accumulator data type, then the outconverter function is mandatory.</p>
+</li>
+
+</ul>
+
+<p>Note that a kernel has input types, an accumulator data item type, and a result type,
+  none of which need to be the same. For example, in
+  the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the input
+  type <code>long</code>, accumulator data item type <code>MinAndMax</code>, and result
+  type <code>int2</code> are all different.</p>
+
+<h4 id="assume">What can't you assume?</h4>
+
+<p>You must not rely on the number of accumulator data items created by RenderScript for a
+  given kernel launch.  There is no guarantee that two launches of the same kernel with the
+  same input(s) will create the same number of accumulator data items.</p>
+
+<p>You must not rely on the order in which RenderScript calls the initializer, accumulator, and
+  combiner functions; it may even call some of them in parallel.  There is no guarantee that
+  two launches of the same kernel with the same input will follow the same order.  The only
+  guarantee is that only the initializer function will ever see an uninitialized accumulator
+  data item. For example:</p>
+<ul>
+<li>There is no guarantee that all accumulator data items will be initialized before the
+  accumulator function is called, although it will only be called on an initialized accumulator
+  data item.</li>
+<li>There is no guarantee on the order in which input Elements are passed to the accumulator
+  function.</li>
+<li>There is no guarantee that the accumulator function has been called for all input Elements
+  before the combiner function is called.</li>
+</ul>
+
+<p>One consequence of this is that the <a href="#example-findMinAndMax">findMinAndMax</a>
+  kernel is not deterministic: If the input contains more than one occurrence of the same
+  minimum or maximum value, you have no way of knowing which occurrence the kernel will
+  find.</p>
+
+<h4 id="guarantee">What must you guarantee?</h4>
+
+<p>Because the RenderScript system can choose to execute a kernel <a href="#assume">in many
+    different ways</a>, you must follow certain rules to ensure that your kernel behaves the
+    way you want. If you do not follow these rules, you may get incorrect results,
+    nondeterministic behavior, or runtime errors.</p>
+
+<p>The rules below often say that two accumulator data items must have "<a id="the-same">the
+  same value"</a>.  What does this mean?  That depends on what you want the kernel to do.  For
+  a mathematical reduction such as <a href="#example-addint">addint</a>, it usually makes sense
+  for "the same" to mean mathematical equality.  For a "pick any" search such
+  as <a href="#example-findMinAndMax">findMinAndMax</a> ("find the location of minimum and
+  maximum input values") where there might be more than one occurrence of identical input
+  values, all locations of a given input value must be considered "the same".  You could write
+  a similar kernel to "find the location of <em>leftmost</em> minimum and maximum input values"
+  where (say) a minimum value at location 100 is preferred over an identical minimum value at location
+  200; for this kernel, "the same" would mean identical <em>location</em>, not merely
+  identical <em>value</em>, and the accumulator and combiner functions would have to be
+  different than those for <a href="#example-findMinAndMax">findMinAndMax</a>.</p>
+
+<strong>The initializer function must create an <i>identity value</i>.</strong>  That is,
+  if <code><i>I</i></code> and <code><i>A</i></code> are accumulator data items initialized
+  by the initializer function, and <code><i>I</i></code> has never been passed to the
+  accumulator function (but <code><i>A</i></code> may have been), then
+<ul>
+<li><code><i>combinerName</i>(&<i>A</i>, &<i>I</i>)</code> must
+  leave <code><i>A</i></code> <a href="#the-same">the same</a></li>
+<li><code><i>combinerName</i>(&<i>I</i>, &<i>A</i>)</code> must
+  leave <code><i>I</i></code> <a href="#the-same">the same</a> as <code><i>A</i></code></li>
+</ul>
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+  kernel, an accumulator data item is initialized to zero. The combiner function for this
+  kernel performs addition; zero is the identity value for addition.</p>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a>
+  kernel, an accumulator data item is initialized
+  to <a href="#INITVAL"><code>INITVAL</code></a>.
+<ul>
+<li><code>fMMCombiner(&<i>A</i>, &<i>I</i>)</code> leaves <code><i>A</i></code> the same,
+  because <code><i>I</i></code> is <code>INITVAL</code>.</li>
+<li><code>fMMCombiner(&<i>I</i>, &<i>A</i>)</code> sets <code><i>I</i></code>
+  to <code><i>A</i></code>, because <code><i>I</i></code> is <code>INITVAL</code>.</li>
+</ul>
+Therefore, <code>INITVAL</code> is indeed an identity value.
+</p></div>
+
+<p><strong>The combiner function must be <i>commutative</i>.</strong>  That is,
+  if <code><i>A</i></code> and <code><i>B</i></code> are accumulator data items initialized
+  by the initializer function, and that may have been passed to the accumulator function zero
+  or more times, then <code><i>combinerName</i>(&<i>A</i>, &<i>B</i>)</code> must
+  set <code><i>A</i></code> to <a href="#the-same">the same value</a>
+  that <code><i>combinerName</i>(&<i>B</i>, &<i>A</i>)</code>
+  sets <code><i>B</i></code>.</p>
+<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a>
+  kernel, the combiner function adds the two accumulator data item values; addition is
+  commutative.</p>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel,
+<pre>
+fMMCombiner(&<i>A</i>, &<i>B</i>)
+</pre>
+is the same as
+<pre>
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+</pre>
+and <code>minmax</code> is commutative, so <code>fMMCombiner</code> is also.
+</p>
+</div>
+
+<p><strong>The combiner function must be <i>associative</i>.</strong>  That is,
+  if <code><i>A</i></code>, <code><i>B</i></code>, and <code><i>C</i></code> are
+  accumulator data items initialized by the initializer function, and that may have been passed
+  to the accumulator function zero or more times, then the following two code sequences must
+  set <code><i>A</i></code> to <a href="#the-same">the same value</a>:</p>
+<ul>
+<li><pre>
+<i>combinerName</i>(&<i>A</i>, &<i>B</i>);
+<i>combinerName</i>(&<i>A</i>, &<i>C</i>);
+</pre></li>
+<li><pre>
+<i>combinerName</i>(&<i>B</i>, &<i>C</i>);
+<i>combinerName</i>(&<i>A</i>, &<i>B</i>);
+</pre></li>
+</ul>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel, the
+  combiner function adds the two accumulator data item values:
+<ul>
+<li><pre>
+<i>A</i> = <i>A</i> + <i>B</i>
+<i>A</i> = <i>A</i> + <i>C</i>
+// Same as
+//   <i>A</i> = (<i>A</i> + <i>B</i>) + <i>C</i>
+</pre></li>
+<li><pre>
+<i>B</i> = <i>B</i> + <i>C</i>
+<i>A</i> = <i>A</i> + <i>B</i>
+// Same as
+//   <i>A</i> = <i>A</i> + (<i>B</i> + <i>C</i>)
+//   <i>B</i> = <i>B</i> + <i>C</i>
+</li>
+</ul>
+Addition is associative, and so the combiner function is also.
+</p>
+</div>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel,
+<pre>
+fMMCombiner(&<i>A</i>, &<i>B</i>)
+</pre>
+is the same as
+<pre>
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+</pre>
+So the two sequences are
+<ul>
+<li><pre>
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+<i>A</i> = minmax(<i>A</i>, <i>C</i>)
+// Same as
+//   <i>A</i> = minmax(minmax(<i>A</i>, <i>B</i>), <i>C</i>)
+</pre></li>
+<li><pre>
+<i>B</i> = minmax(<i>B</i>, <i>C</i>)
+<i>A</i> = minmax(<i>A</i>, <i>B</i>)
+// Same as
+//   <i>A</i> = minmax(<i>A</i>, minmax(<i>B</i>, <i>C</i>))
+//   <i>B</i> = minmax(<i>B</i>, <i>C</i>)
+</pre></li>
+<code>minmax</code> is associative, and so <code>fMMCombiner</code> is also.
+</p>
+</div>
+
+<p><strong>The accumulator function and combiner function together must obey the <i>basic
+  folding rule</i>.</strong>  That is, if <code><i>A</i></code>
+  and <code><i>B</i></code> are accumulator data items, <code><i>A</i></code> has been
+  initialized by the initializer function and may have been passed to the accumulator function
+  zero or more times, <code><i>B</i></code> has not been initialized, and <i>args</i> is
+  the list of input arguments and special arguments for a particular call to the accumulator
+  function, then the following two code sequences must set <code><i>A</i></code>
+  to <a href="#the-same">the same value</a>:</p>
+<ul>
+<li><pre>
+<i>accumulatorName</i>(&<i>A</i>, <i>args</i>);  // statement 1
+</pre></li>
+<li><pre>
+<i>initializerName</i>(&<i>B</i>);        // statement 2
+<i>accumulatorName</i>(&<i>B</i>, <i>args</i>);  // statement 3
+<i>combinerName</i>(&<i>A</i>, &<i>B</i>);       // statement 4
+</pre></li>
+</ul>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel, for an input value <i>V</i>:
+<ul>
+<li>Statement 1 is the same as <code>A += <i>V</i></code></li>
+<li>Statement 2 is the same as <code>B = 0</code></li>
+<li>Statement 3 is the same as <code>B += <i>V</i></code>, which is the same as <code>B = <i>V</i></code></li>
+<li>Statement 4 is the same as <code>A += B</code>, which is the same as <code>A += <i>V</i></code></li>
+</ul>
+Statements 1 and 4 set <code><i>A</i></code> to the same value, and so this kernel obeys the
+basic folding rule.
+</p>
+</div>
+<div class="note">
+<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, for an input
+  value <i>V</i> at coordinate <i>X</i>:
+<ul>
+<li>Statement 1 is the same as <code>A = minmax(A, IndexedVal(<i>V</i>, <i>X</i>))</code></li>
+<li>Statement 2 is the same as <code>B = <a href="#INITVAL">INITVAL</a></code></li>
+<li>Statement 3 is the same as
+<pre>
+B = minmax(B, IndexedVal(<i>V</i>, <i>X</i>))
+</pre>
+which, because <i>B</i> is the initial value, is the same as
+<pre>
+B = IndexedVal(<i>V</i>, <i>X</i>)
+</pre>
+</li>
+<li>Statement 4 is the same as
+<pre>
+A = minmax(A, B)
+</pre>
+which is the same as
+<pre>
+A = minmax(A, IndexedVal(<i>V</i>, <i>X</i>))
+</pre>
+</ul>
+Statements 1 and 4 set <code><i>A</i></code> to the same value, and so this kernel obeys the
+basic folding rule.
+</p>
+</div>
+
+<h3 id="calling-reduction-kernel">Calling a reduction kernel from Java code</h3>
+
+<p>For a reduction kernel named <i>kernelName</i> defined in the
+file <code><i>filename</i>.rs</code>, there are three methods reflected in the
+class <code>ScriptC_<i>filename</i></code>:</p>
+
+<pre>
+// Method 1
+public <i>javaFutureType</i> reduce_<i>kernelName</i>(Allocation ain1, <i>&hellip;,</i>
+                                        Allocation ain<i>N</i>);
+
+// Method 2
+public <i>javaFutureType</i> reduce_<i>kernelName</i>(Allocation ain1, <i>&hellip;,</i>
+                                        Allocation ain<i>N</i>,
+                                        Script.LaunchOptions sc);
+
+// Method 3
+public <i>javaFutureType</i> reduce_<i>kernelName</i>(<i><a href="#devec">devecSiIn1Type</a></i>[] in1, &hellip;,
+                                        <i><a href="#devec">devecSiInNType</a></i>[] in<i>N</i>);
+</pre>
+
+<p>Here are some examples of calling the <a href="#example-addint">addint</a> kernel:</p>
+<pre>
+ScriptC_example script = new ScriptC_example(mRenderScript);
+
+// 1D array
+//   and obtain answer immediately
+int input1[] = <i>&hellip;</i>;
+int sum1 = script.reduce_addint(input1).get();  // Method 3
+
+// 2D allocation
+//   and do some additional work before obtaining answer
+Type.Builder typeBuilder =
+  new Type.Builder(RS, Element.I32(RS));
+typeBuilder.setX(<i>&hellip;</i>);
+typeBuilder.setY(<i>&hellip;</i>);
+Allocation input2 = createTyped(RS, typeBuilder.create());
+<i>populateSomehow</i>(input2);  // fill in input Allocation with data
+script.result_int result2 = script.reduce_addint(input2);  // Method 1
+<i>doSomeAdditionalWork</i>(); // might run at same time as reduction
+int sum2 = result2.get();
+</pre>
+
+<p><strong>Method 1</strong> has one input {@link android.renderscript.Allocation} argument for
+  every input argument in the kernel's <a href="#accumulator-function">accumulator
+    function</a>. The RenderScript runtime checks to ensure that all of the input Allocations
+  have the same dimensions and that the {@link android.renderscript.Element} type of each of
+  the input Allocations matches that of the corresponding input argument of the accumulator
+  function's prototype. If any of these checks fail, RenderScript throws an exception. The
+  kernel executes over every coordinate in those dimensions.</p>
+
+<p><strong>Method 2</strong> is the same as Method 1 except that Method 2 takes an additional
+  argument <code>sc</code> that can be used to limit the kernel execution to a subset of the
+  coordinates.</p>
+
+<p><strong><a id="reduce-method-3">Method 3</a></strong> is the same as Method 1 except that
+  instead of taking Allocation inputs it takes Java array inputs. This is a convenience that
+  saves you from having to write code to explicitly create an Allocation and copy data to it
+  from a Java array. <em>However, using Method 3 instead of Method 1 does not increase the
+  performance of the code</em>. For each input array, Method 3 creates a temporary
+  1-dimensional Allocation with the appropriate {@link android.renderscript.Element} type and
+  {@link android.renderscript.Allocation#setAutoPadding} enabled, and copies the array to the
+  Allocation as if by the appropriate <code>copyFrom()</code> method of {@link
+  android.renderscript.Allocation}. It then calls Method 1, passing those temporary
+  Allocations.</p>
+<p class="note"><strong>NOTE:</strong> If your application will make multiple kernel calls with
+  the same array, or with different arrays of the same dimensions and Element type, you may improve
+  performance by explicitly creating, populating, and reusing Allocations yourself, instead of
+  by using Method 3.</p>
+<p><strong><i><a id="javaFutureType">javaFutureType</a></i></strong>,
+  the return type of the reflected reduction methods, is a reflected
+  static nested class within the <code>ScriptC_<i>filename</i></code>
+  class. It represents the future result of a reduction
+  kernel run. To obtain the actual result of the run, call
+  the <code>get()</code> method of that class, which returns a value
+  of type <i>javaResultType</i>. <code>get()</code> is <a href="#asynchronous-model">synchronous</a>.</p>
+
+<pre>
+public class ScriptC_<i>filename</i> extends ScriptC {
+  public static class <i>javaFutureType</i> {
+    public <i>javaResultType</i> get() { &hellip; }
+  }
+}
+</pre>
+
+<p><strong><i>javaResultType</i></strong> is determined from the <i>resultType</i> of the
+  <a href="#outconverter-function">outconverter function</a>. Unless <i>resultType</i> is an
+  unsigned type (scalar, vector, or array), <i>javaResultType</i> is the directly corresponding
+  Java type. If <i>resultType</i> is an unsigned type and there is a larger Java signed type,
+  then <i>javaResultType</i> is that larger Java signed type; otherwise, it is the directly
+  corresponding Java type. For example:</p>
+<ul>
+<li>If <i>resultType</i> is <code>int</code>, <code>int2</code>, or <code>int[15]</code>,
+  then <i>javaResultType</i> is <code>int</code>, <code>Int2</code>,
+  or <code>int[]</code>. All values of <i>resultType</i> can be represented
+  by <i>javaResultType</i>.</li>
+<li>If <i>resultType</i> is <code>uint</code>, <code>uint2</code>, or <code>uint[15]</code>,
+  then <i>javaResultType</i> is <code>long</code>, <code>Long2</code>,
+  or <code>long[]</code>.  All values of <i>resultType</i> can be represented
+  by <i>javaResultType</i>.</li>
+<li>If <i>resultType</i> is <code>ulong</code>, <code>ulong2</code>,
+  or <code>ulong[15]</code>, then <i>javaResultType</i>
+  is <code>long</code>, <code>Long2</code>, or <code>long[]</code>. There are certain values
+  of <i>resultType</i> that cannot be represented by <i>javaResultType</i>.</li>
+</ul>
+
+<p><strong><i>javaFutureType</i></strong> is the future result type corresponding
+  to the <i>resultType</i> of the <a href="#outconverter-function">outconverter
+  function</a>.</p>
+<ul>
+<li>If <i>resultType</i> is not an array type, then <i>javaFutureType</i>
+  is <code>result_<i>resultType</i></code>.</li>
+<li>If <i>resultType</i> is an array of length <i>Count</i> with members of type <i>memberType</i>,
+  then <i>javaFutureType</i> is <code>resultArray<i>Count</i>_<i>memberType</i></code>.</li>
+</ul>
+
+<p>For example:</p>
+
+<pre>
+public class ScriptC_<i>filename</i> extends ScriptC {
+  // for kernels with int result
+  public static class result_int {
+    public int get() { &hellip; }
+  }
+
+  // for kernels with int[10] result
+  public static class resultArray10_int {
+    public int[] get() { &hellip; }
+  }
+
+  // for kernels with int2 result
+  //   note that the Java type name "Int2" is not the same as the script type name "int2"
+  public static class result_int2 {
+    public Int2 get() { &hellip; }
+  }
+
+  // for kernels with int2[10] result
+  //   note that the Java type name "Int2" is not the same as the script type name "int2"
+  public static class resultArray10_int2 {
+    public Int2[] get() { &hellip; }
+  }
+
+  // for kernels with uint result
+  //   note that the Java type "long" is a wider signed type than the unsigned script type "uint"
+  public static class result_uint {
+    public long get() { &hellip; }
+  }
+
+  // for kernels with uint[10] result
+  //   note that the Java type "long" is a wider signed type than the unsigned script type "uint"
+  public static class resultArray10_uint {
+    public long[] get() { &hellip; }
+  }
+
+  // for kernels with uint2 result
+  //   note that the Java type "Long2" is a wider signed type than the unsigned script type "uint2"
+  public static class result_uint2 {
+    public Long2 get() { &hellip; }
+  }
+
+  // for kernels with uint2[10] result
+  //   note that the Java type "Long2" is a wider signed type than the unsigned script type "uint2"
+  public static class resultArray10_uint2 {
+    public Long2[] get() { &hellip; }
+  }
+}
+</pre>
+
+<p>If <i>javaResultType</i> is an object type (including an array type), each call
+  to <code><i>javaFutureType</i>.get()</code> on the same instance will return the same
+  object.</p>
+
+<p>If <i>javaResultType</i> cannot represent all values of type <i>resultType</i>, and a
+  reduction kernel produces an unrepresentible value,
+  then <code><i>javaFutureType</i>.get()</code> throws an exception.</p>
+
+<h4 id="devec">Method 3 and <i>devecSiInXType</i></h4>
+
+<p><strong><i>devecSiInXType</i></strong> is the Java type corresponding to
+  the <i>inXType</i> of the corresponding argument of
+  the <a href="#accumulator-function">accumulator function</a>. Unless <i>inXType</i> is an
+  unsigned type or a vector type, <i>devecSiInXType</i> is the directly corresponding Java
+  type. If <i>inXType</i> is an unsigned scalar type, then <i>devecSiInXType</i> is the
+  Java type directly corresponding to the signed scalar type of the same
+  size. If <i>inXType</i> is a signed vector type, then <i>devecSiInXType</i> is the Java
+  type directly corresponding to the vector component type. If <i>inXType</i> is an unsigned
+  vector type, then <i>devecSiInXType</i> is the Java type directly corresponding to the
+  signed scalar type of the same size as the vector component type. For example:</p>
+<ul>
+<li>If <i>inXType</i> is <code>int</code>, then <i>devecSiInXType</i>
+  is <code>int</code>.</li>
+<li>If <i>inXType</i> is <code>int2</code>, then <i>devecSiInXType</i>
+  is <code>int</code>. The array is a <em>flattened</em> representation: It has twice as
+  many <em>scalar</em> Elements as the Allocation has 2-component <em>vector</em>
+  Elements. This is the same way that the <code>copyFrom()</code> methods of {@link
+  android.renderscript.Allocation} work.</li>
+<li>If <i>inXType</i> is <code>uint</code>, then <i>deviceSiInXType</i>
+  is <code>int</code>. A signed value in the Java array is interpreted as an unsigned value of
+  the same bitpattern in the Allocation. This is the same way that the <code>copyFrom()</code>
+  methods of {@link android.renderscript.Allocation} work.</li>
+<li>If <i>inXType</i> is <code>uint2</code>, then <i>deviceSiInXType</i>
+  is <code>int</code>. This is a combination of the way <code>int2</code> and <code>uint</code>
+  are handled: The array is a flattened representation, and Java array signed values are
+  interpreted as RenderScript unsigned Element values.</li>
+</ul>
+
+<p>Note that for <a href="#reduce-method-3">Method 3</a>, input types are handled differently
+than result types:</p>
+
+<ul>
+<li>A script's vector input is flattened on the Java side, whereas a script's vector result is not.</li>
+<li>A script's unsigned input is represented as a signed input of the same size on the Java
+  side, whereas a script's unsigned result is represented as a widened signed type on the Java
+  side (except in the case of <code>ulong</code>).</li>
+</ul>
+
+<h3 id="more-example">More example reduction kernels</h3>
+
+<pre id="dot-product">
+#pragma rs reduce(dotProduct) \
+  accumulator(dotProductAccum) combiner(dotProductSum)
+
+// Note: No initializer function -- therefore,
+// each accumulator data item is implicitly initialized to 0.0f.
+
+static void dotProductAccum(float *accum, float in1, float in2) {
+  *accum += in1*in2;
+}
+
+// combiner function
+static void dotProductSum(float *accum, const float *val) {
+  *accum += *val;
+}
+</pre>
+
+<pre>
+// Find a zero Element in a 2D allocation; return (-1, -1) if none
+#pragma rs reduce(fz2) \
+  initializer(fz2Init) \
+  accumulator(fz2Accum) combiner(fz2Combine)
+
+static void fz2Init(int2 *accum) { accum->x = accum->y = -1; }
+
+static void fz2Accum(int2 *accum,
+                     int inVal,
+                     int x /* special arg */,
+                     int y /* special arg */) {
+  if (inVal==0) {
+    accum->x = x;
+    accum->y = y;
+  }
+}
+
+static void fz2Combine(int2 *accum, const int2 *accum2) {
+  if (accum2->x >= 0) *accum = *accum2;
+}
+</pre>
+
+<pre>
+// Note that this kernel returns an array to Java
+#pragma rs reduce(histogram) \
+  accumulator(hsgAccum) combiner(hsgCombine)
+
+#define BUCKETS 256
+typedef uint32_t Histogram[BUCKETS];
+
+// Note: No initializer function --
+// therefore, each bucket is implicitly initialized to 0.
+
+static void hsgAccum(Histogram *h, uchar in) { ++(*h)[in]; }
+
+static void hsgCombine(Histogram *accum,
+                       const Histogram *addend) {
+  for (int i = 0; i < BUCKETS; ++i)
+    (*accum)[i] += (*addend)[i];
+}
+
+// Determines the mode (most frequently occurring value), and returns
+// the value and the frequency.
+//
+// If multiple values have the same highest frequency, returns the lowest
+// of those values.
+//
+// Shares functions with the histogram reduction kernel.
+#pragma rs reduce(mode) \
+  accumulator(hsgAccum) combiner(hsgCombine) \
+  outconverter(modeOutConvert)
+
+static void modeOutConvert(int2 *result, const Histogram *h) {
+  uint32_t mode = 0;
+  for (int i = 1; i < BUCKETS; ++i)
+    if ((*h)[i] > (*h)[mode]) mode = i;
+  result->x = mode;
+  result->y = (*h)[mode];
+}
+</pre>
diff --git a/docs/html/training/testing/unit-testing/local-unit-tests.jd b/docs/html/training/testing/unit-testing/local-unit-tests.jd
index 8b109ee..d19de4f 100644
--- a/docs/html/training/testing/unit-testing/local-unit-tests.jd
+++ b/docs/html/training/testing/unit-testing/local-unit-tests.jd
@@ -112,12 +112,16 @@
 returned result against the expected result.</p>
 
 <h3 id="mocking-dependencies">Mock Android dependencies</h3>
-<p>
-By default, the <a href="{@docRoot}tools/building/plugin-for-gradle.html">
-Android Plug-in for Gradle</a> executes your local unit tests against a modified
-version of the {@code android.jar} library, which does not contain any actual code. Instead, method
-calls to Android classes from your unit test throw an exception.
-</p>
+
+<p>By default, the <a href=
+"{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for
+Gradle</a> executes your local unit tests against a modified version of the
+{@code android.jar} library, which does not contain any actual code. Instead,
+method calls to Android classes from your unit test throw an exception. This is
+to make sure you test only your code and do not depend on any
+particular behavior of the Android platform (that you have not explicitly
+mocked).</p>
+
 <p>
 You can use a mocking framework to stub out external dependencies in your code, to easily test that
 your component interacts with a dependency in an expected way. By substituting Android dependencies
@@ -195,6 +199,26 @@
 class="external-link">sample code</a>.
 </p>
 
+<p>If the exceptions thrown by Android APIs in the
+<code>android.jar</code> are problematic for your tests, you can change the behavior so that methods
+instead return either null or zero by adding the following configuration in your project's
+top-level <code>build.gradle</code> file:</p>
+
+<pre>
+android {
+  ...
+  testOptions {
+    unitTests.returnDefaultValues = true
+  }
+}
+</pre>
+
+<p class="caution"><strong>Caution:</strong>
+Setting the <code>returnDefaultValues</code> property to <code>true</code>
+should be done with care. The null/zero return values can introduce
+regressions in your tests, which are hard to debug and might allow failing tests
+to pass. Only use it as a last resort.</p>
+
 
 <h2 id="run">Run Local Unit Tests</h2>
 
diff --git a/libs/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp
index f72ffaa..b1495ef 100644
--- a/libs/common_time/common_time_server.cpp
+++ b/libs/common_time/common_time_server.cpp
@@ -615,12 +615,11 @@
 
     ssize_t recvBytes = recvfrom(
             mSocket, buf, sizeof(buf), 0,
-            reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen);
+            reinterpret_cast<sockaddr *>(&srcAddr), &srcAddrLen);
 
     if (recvBytes < 0) {
-        mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG,
-                       "recvfrom failed (res %d, errno %d)",
-                       recvBytes, errno);
+        mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG, "recvfrom failed (%s)",
+                       strerror(errno));
         return false;
     }
 
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 72bac6c..aac355c 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -124,7 +124,7 @@
         Finished,
     };
 
-    BaseRenderNodeAnimator(float finalValue);
+    explicit BaseRenderNodeAnimator(float finalValue);
     virtual ~BaseRenderNodeAnimator();
 
     virtual float getValue(RenderNode* target) const = 0;
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index 6afff1b..e2e70372 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -27,7 +27,7 @@
 // Lifecycle
 ///////////////////////////////////////////////////////////////////////////////
 
-void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) {
+void AssetAtlas::init(const sp<GraphicBuffer>& buffer, int64_t* map, int count) {
     if (mImage) {
         return;
     }
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 75400ff..b32e518 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -109,7 +109,7 @@
      * initialized. To re-initialize the atlas, you must
      * first call terminate().
      */
-    ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count);
+    ANDROID_API void init(const sp<GraphicBuffer>& buffer, int64_t* map, int count);
 
     /**
      * Destroys the atlas texture. This object can be
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index a8205c8..c5d8767 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -101,7 +101,7 @@
 
     const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
     const LsaVector<FunctorContainer>& getFunctors() const { return functors; }
-    const LsaVector<VectorDrawableRoot*>& getVectorDrawables() { return vectorDrawables; }
+    const LsaVector<VectorDrawableRoot*>& getVectorDrawables() const { return vectorDrawables; }
 
     size_t addChild(NodeOpType* childOp);
 
diff --git a/libs/hwui/Image.h b/libs/hwui/Image.h
index 2514535..b8f5a5b 100644
--- a/libs/hwui/Image.h
+++ b/libs/hwui/Image.h
@@ -38,7 +38,7 @@
      * cannot be created, getTexture() will return 0 and getImage() will
      * return EGL_NO_IMAGE_KHR.
      */
-    Image(sp<GraphicBuffer> buffer);
+    explicit Image(sp<GraphicBuffer> buffer);
     ~Image();
 
     /**
diff --git a/libs/hwui/Interpolator.h b/libs/hwui/Interpolator.h
index 66ce119..6512008 100644
--- a/libs/hwui/Interpolator.h
+++ b/libs/hwui/Interpolator.h
@@ -43,7 +43,7 @@
 
 class ANDROID_API AccelerateInterpolator : public Interpolator {
 public:
-    AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor*2) {}
+    explicit AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor*2) {}
     virtual float interpolate(float input) override;
 private:
     const float mFactor;
@@ -52,7 +52,7 @@
 
 class ANDROID_API AnticipateInterpolator : public Interpolator {
 public:
-    AnticipateInterpolator(float tension) : mTension(tension) {}
+    explicit AnticipateInterpolator(float tension) : mTension(tension) {}
     virtual float interpolate(float input) override;
 private:
     const float mTension;
@@ -60,7 +60,7 @@
 
 class ANDROID_API AnticipateOvershootInterpolator : public Interpolator {
 public:
-    AnticipateOvershootInterpolator(float tension) : mTension(tension) {}
+    explicit AnticipateOvershootInterpolator(float tension) : mTension(tension) {}
     virtual float interpolate(float input) override;
 private:
     const float mTension;
@@ -73,7 +73,7 @@
 
 class ANDROID_API CycleInterpolator : public Interpolator {
 public:
-    CycleInterpolator(float cycles) : mCycles(cycles) {}
+    explicit CycleInterpolator(float cycles) : mCycles(cycles) {}
     virtual float interpolate(float input) override;
 private:
     const float mCycles;
@@ -81,7 +81,7 @@
 
 class ANDROID_API DecelerateInterpolator : public Interpolator {
 public:
-    DecelerateInterpolator(float factor) : mFactor(factor) {}
+    explicit DecelerateInterpolator(float factor) : mFactor(factor) {}
     virtual float interpolate(float input) override;
 private:
     const float mFactor;
@@ -94,7 +94,7 @@
 
 class ANDROID_API OvershootInterpolator : public Interpolator {
 public:
-    OvershootInterpolator(float tension) : mTension(tension) {}
+    explicit OvershootInterpolator(float tension) : mTension(tension) {}
     virtual float interpolate(float input) override;
 private:
     const float mTension;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index c90abad..dd20a76 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -23,6 +23,7 @@
 #include "RecordedOp.h"
 #include "TreeInfo.h"
 #include "utils/MathUtils.h"
+#include "utils/StringUtils.h"
 #include "utils/TraceUtils.h"
 #include "VectorDrawable.h"
 #include "renderstate/RenderState.h"
@@ -68,31 +69,36 @@
  * This function is a simplified version of replay(), where we simply retrieve and log the
  * display list. This function should remain in sync with the replay() function.
  */
-void RenderNode::output(uint32_t level, const char* label) {
-    ALOGD("%s (%s %p%s%s%s%s%s)",
-            label,
-            getName(),
-            this,
-            (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : ""),
-            (properties().hasShadow() ? ", casting shadow" : ""),
-            (isRenderable() ? "" : ", empty"),
-            (properties().getProjectBackwards() ? ", projected" : ""),
-            (mLayer != nullptr ? ", on HW Layer" : ""));
-    properties().debugOutputProperties(level + 1);
+void RenderNode::output() {
+    LogcatStream strout;
+    strout << "Root";
+    output(strout, 0);
+}
+
+void RenderNode::output(std::ostream& output, uint32_t level) {
+    output << "  (" << getName() << " " << this
+            << (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : "")
+            << (properties().hasShadow() ? ", casting shadow" : "")
+            << (isRenderable() ? "" : ", empty")
+            << (properties().getProjectBackwards() ? ", projected" : "")
+            << (mLayer != nullptr ? ", on HW Layer" : "")
+            << ")" << std::endl;
+
+    properties().debugOutputProperties(output, level + 1);
 
     if (mDisplayList) {
         for (auto&& op : mDisplayList->getOps()) {
-            std::stringstream strout;
-            OpDumper::dump(*op, strout, level + 1);
+            OpDumper::dump(*op, output, level + 1);
             if (op->opId == RecordedOpId::RenderNodeOp) {
                 auto rnOp = reinterpret_cast<const RenderNodeOp*>(op);
-                rnOp->renderNode->output(level + 1, strout.str().c_str());
+                rnOp->renderNode->output(output, level + 1);
             } else {
-                ALOGD("%s", strout.str().c_str());
+                output << std::endl;
             }
         }
     }
-    ALOGD("%*s/RenderNode(%s %p)", level * 2, "", getName(), this);
+    output << std::string(level * 2, ' ') << "/RenderNode(" << getName() << " " << this << ")";
+    output << std::endl;
 }
 
 void RenderNode::copyTo(proto::RenderNode *pnode) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index ee045aa..a0679b1 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -102,7 +102,7 @@
 
     void computeOrdering();
 
-    ANDROID_API void output(uint32_t level = 0, const char* label = "Root");
+    ANDROID_API void output();
     ANDROID_API int getDebugSize();
     void copyTo(proto::RenderNode* node);
 
@@ -247,6 +247,7 @@
 
     void incParentRefCount() { mParentCount++; }
     void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr);
+    void output(std::ostream& output, uint32_t level);
 
     String8 mName;
     sp<VirtualLightRefBase> mUserContext;
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 7e3cad4..b0114bc 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -99,26 +99,34 @@
     return *this;
 }
 
-void RenderProperties::debugOutputProperties(const int level) const {
+static void dumpMatrix(std::ostream& output, std::string& indent,
+        const char* label, SkMatrix* matrix) {
+   if (matrix) {
+        output << indent << "(" <<  label << " " << matrix << ": ";
+        output << std::fixed << std::setprecision(2);
+        output << "[" << matrix->get(0) << " "<< matrix->get(1) << " " << matrix->get(2) << "]";
+        output << " [" << matrix->get(3) << " "<< matrix->get(4) << " " << matrix->get(5) << "]";
+        output << " [" << matrix->get(6) << " "<< matrix->get(7) << " " << matrix->get(8) << "]";
+        output << ")" << std::endl;
+    }
+}
+
+void RenderProperties::debugOutputProperties(std::ostream& output, const int level) const {
+    auto indent = std::string(level * 2, ' ');
     if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) {
-        ALOGD("%*s(Translate (left, top) %d, %d)", level * 2, "",
-                mPrimitiveFields.mLeft, mPrimitiveFields.mTop);
+        output << indent << "(Translate (left, top) " << mPrimitiveFields.mLeft
+                << ", " << mPrimitiveFields.mTop << ")" << std::endl;
     }
-    if (mStaticMatrix) {
-        ALOGD("%*s(ConcatMatrix (static) %p: " SK_MATRIX_STRING ")",
-                level * 2, "", mStaticMatrix, SK_MATRIX_ARGS(mStaticMatrix));
-    }
-    if (mAnimationMatrix) {
-        ALOGD("%*s(ConcatMatrix (animation) %p: " SK_MATRIX_STRING ")",
-                level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix));
-    }
+    dumpMatrix(output, indent, "ConcatMatrix (static)", mStaticMatrix);
+    dumpMatrix(output, indent, "ConcatMatrix (animation)", mAnimationMatrix);
+
+    output << std::fixed << std::setprecision(2);
     if (hasTransformMatrix()) {
         if (isTransformTranslateOnly()) {
-            ALOGD("%*s(Translate %.2f, %.2f, %.2f)",
-                    level * 2, "", getTranslationX(), getTranslationY(), getZ());
+            output << indent << "(Translate " << getTranslationX() << ", " << getTranslationY()
+                    << ", " << getZ() << ")" << std::endl;
         } else {
-            ALOGD("%*s(ConcatMatrix %p: " SK_MATRIX_STRING ")",
-                    level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix));
+            dumpMatrix(output, indent, "ConcatMatrix ", mComputedFields.mTransformMatrix);
         }
     }
 
@@ -132,7 +140,7 @@
 
         if (CC_LIKELY(isLayer || !getHasOverlappingRendering())) {
             // simply scale rendering content's alpha
-            ALOGD("%*s(ScaleAlpha %.2f)", level * 2, "", mPrimitiveFields.mAlpha);
+            output << indent << "(ScaleAlpha " << mPrimitiveFields.mAlpha << ")" << std::endl;
         } else {
             // savelayeralpha to create an offscreen buffer to apply alpha
             Rect layerBounds(0, 0, getWidth(), getHeight());
@@ -140,35 +148,40 @@
                 getClippingRectForFlags(clipFlags, &layerBounds);
                 clipFlags = 0; // all clipping done by savelayer
             }
-            ALOGD("%*s(SaveLayerAlpha %d, %d, %d, %d, %d, 0x%x)", level * 2, "",
-                    (int)layerBounds.left, (int)layerBounds.top,
-                    (int)layerBounds.right, (int)layerBounds.bottom,
-                    (int)(mPrimitiveFields.mAlpha * 255),
-                    SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer);
+            output << indent << "(SaveLayerAlpha "
+                    << (int)layerBounds.left << ", " << (int)layerBounds.top << ", "
+                    << (int)layerBounds.right << ", " << (int)layerBounds.bottom << ", "
+                    << (int)(mPrimitiveFields.mAlpha * 255) << ", 0x" << std::hex
+                    << (SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer) << ")" << std::dec
+                    << std::endl;
         }
     }
 
     if (clipFlags) {
         Rect clipRect;
         getClippingRectForFlags(clipFlags, &clipRect);
-        ALOGD("%*s(ClipRect %d, %d, %d, %d)", level * 2, "",
-                (int)clipRect.left, (int)clipRect.top, (int)clipRect.right, (int)clipRect.bottom);
+        output << indent << "(ClipRect "
+                << (int)clipRect.left << ", " << (int)clipRect.top << ", "
+                << (int)clipRect.right << ", " << (int)clipRect.bottom << ")" << std::endl;
     }
 
     if (getRevealClip().willClip()) {
         Rect bounds;
         getRevealClip().getBounds(&bounds);
-        ALOGD("%*s(Clip to reveal clip with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
-                RECT_ARGS(bounds));
+        output << indent << "(Clip to reveal clip with bounds "
+                << bounds.left << ", " << bounds.top << ", "
+                << bounds.right << ", " << bounds.bottom << ")" << std::endl;
     }
 
     auto& outline = mPrimitiveFields.mOutline;
     if (outline.getShouldClip()) {
         if (outline.isEmpty()) {
-            ALOGD("%*s(Clip to empty outline)", level * 2, "");
+            output << indent << "(Clip to empty outline)";
         } else if (outline.willClip()) {
-            ALOGD("%*s(Clip to outline with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
-                    RECT_ARGS(outline.getBounds()));
+            const Rect& bounds = outline.getBounds();
+            output << indent << "(Clip to outline with bounds "
+                    << bounds.left << ", " << bounds.top << ", "
+                    << bounds.right << ", " << bounds.bottom << ")" << std::endl;
         }
     }
 }
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 00494a1..2f5223c 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -35,6 +35,7 @@
 #include <cutils/compiler.h>
 #include <androidfw/ResourceTypes.h>
 #include <utils/Log.h>
+#include <ostream>
 
 class SkBitmap;
 class SkColorFilter;
@@ -574,7 +575,7 @@
         return mPrimitiveFields.mProjectBackwards;
     }
 
-    void debugOutputProperties(const int level) const;
+    void debugOutputProperties(std::ostream& output, const int level) const;
 
     void updateMatrix();
 
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 731d9bb..9e0fb12 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -106,7 +106,7 @@
     void interruptForFunctorInvoke();
     void resumeFromFunctorInvoke();
 
-    RenderState(renderthread::RenderThread& thread);
+    explicit RenderState(renderthread::RenderThread& thread);
     ~RenderState();
 
 
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 459baed..41047fe 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -86,7 +86,7 @@
 private:
     friend class RenderThread;
 
-    EglManager(RenderThread& thread);
+    explicit EglManager(RenderThread& thread);
     // EglContext is never destroyed, method is purposely not implemented
     ~EglManager();
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index d6eea87..3edd423 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -157,7 +157,7 @@
     SETUP_TASK(updateSurface);
     args->context = mContext;
     args->surface = surface.get();
-    postAndWait(task);
+    post(task);
 }
 
 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index fd3cf37..0d90afa 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <gtest/gtest.h>
+#include <VectorDrawable.h>
 
 #include "AnimationContext.h"
 #include "DamageAccumulator.h"
@@ -132,3 +133,38 @@
 
     canvasContext->destroy(nullptr);
 }
+
+RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
+
+    VectorDrawable::Group* group = new VectorDrawable::Group();
+    VectorDrawableRoot* vectorDrawable = new VectorDrawableRoot(group);
+    auto rootNode = TestUtils::createNode(0, 0, 200, 400,
+            [&](RenderProperties& props, Canvas& canvas) {
+        canvas.drawVectorDrawable(vectorDrawable);
+    });
+    ContextFactory contextFactory;
+    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+            renderThread, false, rootNode.get(), &contextFactory));
+    TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+    DamageAccumulator damageAccumulator;
+    LayerUpdateQueue layerUpdateQueue;
+    info.damageAccumulator = &damageAccumulator;
+    info.layerUpdateQueue = &layerUpdateQueue;
+    info.observer = nullptr;
+
+    // Put node on HW layer
+    rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+
+    TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
+    rootNode->prepareTree(info);
+
+    // Check that the VD is in the dislay list, and the layer update queue contains the correct
+    // damage rect.
+    EXPECT_FALSE(rootNode->getDisplayList()->getVectorDrawables().empty());
+    EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
+    EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
+    EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
+
+    delete vectorDrawable;
+    canvasContext->destroy(nullptr);
+}
diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h
index 0e4ffdc..c9d12bc 100644
--- a/libs/hwui/thread/TaskManager.h
+++ b/libs/hwui/thread/TaskManager.h
@@ -78,7 +78,7 @@
 
     class WorkerThread: public Thread {
     public:
-        explicit WorkerThread(const String8 name): mSignal(Condition::WAKE_UP_ONE), mName(name) { }
+        explicit WorkerThread(const String8& name): mSignal(Condition::WAKE_UP_ONE), mName(name) { }
 
         bool addTask(const TaskWrapper& task);
         size_t getTaskCount() const;
diff --git a/libs/hwui/utils/StringUtils.h b/libs/hwui/utils/StringUtils.h
index 5add957..af5d10f 100644
--- a/libs/hwui/utils/StringUtils.h
+++ b/libs/hwui/utils/StringUtils.h
@@ -16,10 +16,14 @@
 #ifndef STRING_UTILS_H
 #define STRING_UTILS_H
 
+#include <iomanip>
+#include <iostream>
+#include <ostream>
+#include <sstream>
 #include <string>
 #include <unordered_set>
-#include <ostream>
-#include <iomanip>
+
+#include <utils/Log.h>
 
 namespace android {
 namespace uirenderer {
@@ -51,6 +55,22 @@
     }
 };
 
+class LogcatStream: public std::ostream {
+    class LogcatStreamBuf: public std::stringbuf {
+        virtual int sync() {
+            ALOGD("%s", str().c_str());
+            str("");
+            return 0;
+        }
+    };
+
+    LogcatStreamBuf buffer;
+public:
+    LogcatStream()
+            :std::ostream(&buffer) {
+    }
+};
+
 } /* namespace uirenderer */
 } /* namespace android */
 
diff --git a/libs/hwui/utils/Timing.h b/libs/hwui/utils/Timing.h
index dd8847a..4b1fabe 100644
--- a/libs/hwui/utils/Timing.h
+++ b/libs/hwui/utils/Timing.h
@@ -22,7 +22,7 @@
 #define TIME_METHOD() MethodTimer __method_timer(__func__)
 class MethodTimer {
 public:
-    MethodTimer(const char* name)
+    explicit MethodTimer(const char* name)
             : mMethodName(name) {
         gettimeofday(&mStart, nullptr);
     }
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 268e442..d413083 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -25,6 +25,7 @@
 import android.system.OsConstants;
 import android.util.Log;
 import android.util.Pair;
+import android.annotation.IntDef;
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
@@ -55,6 +56,8 @@
 import java.util.TimeZone;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 import libcore.io.IoUtils;
 import libcore.io.Streams;
@@ -69,7 +72,6 @@
 public class ExifInterface {
     private static final String TAG = "ExifInterface";
     private static final boolean DEBUG = false;
-    private static final boolean HANDLE_RAW = false;
 
     // The Exif tag names. See Tiff 6.0 Section 3 and Section 8.
     /** Type is String. */
@@ -1167,16 +1169,24 @@
     // The following values are used for indicating pointers to the other Image File Directories.
 
     // Indices of Exif Ifd tag groups
-    private static final int IFD_TIFF_HINT = 0;
-    private static final int IFD_EXIF_HINT = 1;
-    private static final int IFD_GPS_HINT = 2;
-    private static final int IFD_INTEROPERABILITY_HINT = 3;
-    private static final int IFD_THUMBNAIL_HINT = 4;
-    private static final int IFD_PREVIEW_HINT = 5;
-    private static final int ORF_MAKER_NOTE_HINT = 6;
-    private static final int ORF_CAMERA_SETTINGS_HINT = 7;
-    private static final int ORF_IMAGE_PROCESSING_HINT = 8;
-    private static final int PEF_HINT = 9;
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({IFD_TYPE_PRIMARY, IFD_TYPE_EXIF, IFD_TYPE_GPS, IFD_TYPE_INTEROPERABILITY,
+            IFD_TYPE_THUMBNAIL, IFD_TYPE_PREVIEW, IFD_TYPE_ORF_MAKER_NOTE,
+            IFD_TYPE_ORF_CAMERA_SETTINGS, IFD_TYPE_ORF_IMAGE_PROCESSING, IFD_TYPE_PEF})
+    public @interface IfdType {}
+
+    private static final int IFD_TYPE_PRIMARY = 0;
+    private static final int IFD_TYPE_EXIF = 1;
+    private static final int IFD_TYPE_GPS = 2;
+    private static final int IFD_TYPE_INTEROPERABILITY = 3;
+    private static final int IFD_TYPE_THUMBNAIL = 4;
+    private static final int IFD_TYPE_PREVIEW = 5;
+    private static final int IFD_TYPE_ORF_MAKER_NOTE = 6;
+    private static final int IFD_TYPE_ORF_CAMERA_SETTINGS = 7;
+    private static final int IFD_TYPE_ORF_IMAGE_PROCESSING = 8;
+    private static final int IFD_TYPE_PEF = 9;
+
     // List of Exif tag groups
     private static final ExifTag[][] EXIF_TAGS = new ExifTag[][] {
             IFD_TIFF_TAGS, IFD_EXIF_TAGS, IFD_GPS_TAGS, IFD_INTEROPERABILITY_TAGS,
@@ -1192,11 +1202,7 @@
             new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_BYTE),
             new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_BYTE)
     };
-    // List of indices of the indicated tag groups according to the EXIF_POINTER_TAGS
-    private static final int[] EXIF_POINTER_TAG_HINTS = new int[] {
-            IFD_PREVIEW_HINT, IFD_EXIF_HINT, IFD_GPS_HINT, IFD_INTEROPERABILITY_HINT,
-            ORF_CAMERA_SETTINGS_HINT, ORF_IMAGE_PROCESSING_HINT
-    };
+
     // Tags for indicating the thumbnail offset and length
     private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG =
             new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG);
@@ -1210,6 +1216,8 @@
     private static final HashSet<String> sTagSetForCompatibility = new HashSet<>(Arrays.asList(
             TAG_F_NUMBER, TAG_DIGITAL_ZOOM_RATIO, TAG_EXPOSURE_TIME, TAG_SUBJECT_DISTANCE,
             TAG_GPS_TIMESTAMP));
+    // Mappings from tag number to IFD type for pointer tags.
+    private static final HashMap sExifPointerTagMap = new HashMap();
 
     // See JPEG File Interchange Format Version 1.02.
     // The following values are defined for handling JPEG streams. In this implementation, we are
@@ -1257,27 +1265,32 @@
     private static final int IMAGE_TYPE_SRW = 11;
 
     static {
-        System.loadLibrary("media_jni");
-        nativeInitRaw();
         sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
         sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
 
         // Build up the hash tables to look up Exif tags for reading Exif tags.
-        for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            sExifTagMapsForReading[hint] = new HashMap();
-            sExifTagMapsForWriting[hint] = new HashMap();
-            for (ExifTag tag : EXIF_TAGS[hint]) {
-                sExifTagMapsForReading[hint].put(tag.number, tag);
-                sExifTagMapsForWriting[hint].put(tag.name, tag);
+        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+            sExifTagMapsForReading[ifdType] = new HashMap();
+            sExifTagMapsForWriting[ifdType] = new HashMap();
+            for (ExifTag tag : EXIF_TAGS[ifdType]) {
+                sExifTagMapsForReading[ifdType].put(tag.number, tag);
+                sExifTagMapsForWriting[ifdType].put(tag.name, tag);
             }
         }
+
+        // Build up the hash table to look up Exif pointer tags.
+        sExifPointerTagMap.put(EXIF_POINTER_TAGS[0].number, IFD_TYPE_PREVIEW); // 330
+        sExifPointerTagMap.put(EXIF_POINTER_TAGS[1].number, IFD_TYPE_EXIF); // 34665
+        sExifPointerTagMap.put(EXIF_POINTER_TAGS[2].number, IFD_TYPE_GPS); // 34853
+        sExifPointerTagMap.put(EXIF_POINTER_TAGS[3].number, IFD_TYPE_INTEROPERABILITY); // 40965
+        sExifPointerTagMap.put(EXIF_POINTER_TAGS[4].number, IFD_TYPE_ORF_CAMERA_SETTINGS); // 8224
+        sExifPointerTagMap.put(EXIF_POINTER_TAGS[5].number, IFD_TYPE_ORF_IMAGE_PROCESSING); // 8256
     }
 
     private final String mFilename;
     private final FileDescriptor mSeekableFileDescriptor;
     private final AssetManager.AssetInputStream mAssetInputStream;
     private final boolean mIsInputStream;
-    private boolean mIsRaw;
     private int mMimeType;
     private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
     private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN;
@@ -1507,7 +1520,7 @@
         }
 
         for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
-            if (i == IFD_THUMBNAIL_HINT && !mHasThumbnail) {
+            if (i == IFD_TYPE_THUMBNAIL && !mHasThumbnail) {
                 continue;
             }
             final Object obj = sExifTagMapsForWriting[i].get(tag);
@@ -1660,71 +1673,44 @@
                 mAttributes[i] = new HashMap();
             }
 
-            if (HANDLE_RAW) {
-                // Check file type
-                in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE);
-                mMimeType = getMimeType((BufferedInputStream) in);
+            // Check file type
+            in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE);
+            mMimeType = getMimeType((BufferedInputStream) in);
 
-                switch (mMimeType) {
-                    case IMAGE_TYPE_JPEG: {
-                        getJpegAttributes(in, 0, IFD_TIFF_HINT); // 0 is offset
-                        break;
-                    }
-                    case IMAGE_TYPE_RAF: {
-                        getRafAttributes(in);
-                        break;
-                    }
-                    case IMAGE_TYPE_ORF: {
-                        getOrfAttributes(in);
-                        break;
-                    }
-                    case IMAGE_TYPE_RW2: {
-                        getRw2Attributes(in);
-                        break;
-                    }
-                    case IMAGE_TYPE_ARW:
-                    case IMAGE_TYPE_CR2:
-                    case IMAGE_TYPE_DNG:
-                    case IMAGE_TYPE_NEF:
-                    case IMAGE_TYPE_NRW:
-                    case IMAGE_TYPE_PEF:
-                    case IMAGE_TYPE_SRW:
-                    case IMAGE_TYPE_UNKNOWN: {
-                        getRawAttributes(in);
-                        break;
-                    }
-                    default: {
-                        break;
-                    }
+            switch (mMimeType) {
+                case IMAGE_TYPE_JPEG: {
+                    getJpegAttributes(in, 0, IFD_TYPE_PRIMARY); // 0 is offset
+                    break;
                 }
-                // Set thumbnail image offset and length
-                setThumbnailData(in);
-            } else {
-                if (mAssetInputStream != null) {
-                    long asset = mAssetInputStream.getNativeAsset();
-                    if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) {
-                        return;
-                    }
-                } else if (mSeekableFileDescriptor != null) {
-                    if (handleRawResult(nativeGetRawAttributesFromFileDescriptor(
-                            mSeekableFileDescriptor))) {
-                        return;
-                    }
-                } else {
-                    in.mark(JPEG_SIGNATURE.length);
-                    byte[] signatureBytes = new byte[JPEG_SIGNATURE.length];
-                    if (in.read(signatureBytes) != JPEG_SIGNATURE.length) {
-                        throw new EOFException();
-                    }
-                    in.reset();
-                    if (!isJpegFormat(signatureBytes) && handleRawResult(
-                            nativeGetRawAttributesFromInputStream(in))) {
-                        return;
-                    }
+                case IMAGE_TYPE_RAF: {
+                    getRafAttributes(in);
+                    break;
                 }
-                // Process JPEG input stream
-                getJpegAttributes(in, 0, IFD_TIFF_HINT);
+                case IMAGE_TYPE_ORF: {
+                    getOrfAttributes(in);
+                    break;
+                }
+                case IMAGE_TYPE_RW2: {
+                    getRw2Attributes(in);
+                    break;
+                }
+                case IMAGE_TYPE_ARW:
+                case IMAGE_TYPE_CR2:
+                case IMAGE_TYPE_DNG:
+                case IMAGE_TYPE_NEF:
+                case IMAGE_TYPE_NRW:
+                case IMAGE_TYPE_PEF:
+                case IMAGE_TYPE_SRW:
+                case IMAGE_TYPE_UNKNOWN: {
+                    getRawAttributes(in);
+                    break;
+                }
+                default: {
+                    break;
+                }
             }
+            // Set thumbnail image offset and length
+            setThumbnailData(in);
         } catch (IOException e) {
             // Ignore exceptions in order to keep the compatibility with the old versions of
             // ExifInterface.
@@ -1742,36 +1728,6 @@
         }
     }
 
-    private boolean handleRawResult(HashMap map) {
-        if (map == null) {
-            if (DEBUG) {
-                Log.d(TAG, "Raw image file not detected");
-            }
-            return false;
-        }
-
-        // Mark for disabling the save feature.
-        mIsRaw = true;
-
-        String value = (String) map.remove(TAG_HAS_THUMBNAIL);
-        mHasThumbnail = value != null && value.equalsIgnoreCase("true");
-        value = (String) map.remove(TAG_THUMBNAIL_OFFSET);
-        if (value != null) {
-            mThumbnailOffset = Integer.parseInt(value);
-        }
-        value = (String) map.remove(TAG_THUMBNAIL_LENGTH);
-        if (value != null) {
-            mThumbnailLength = Integer.parseInt(value);
-        }
-        mThumbnailBytes = (byte[]) map.remove(TAG_THUMBNAIL_DATA);
-
-        for (Map.Entry entry : (Set<Map.Entry>) map.entrySet()) {
-            setAttribute((String) entry.getKey(), (String) entry.getValue());
-        }
-
-        return true;
-    }
-
     private static boolean isSeekableFD(FileDescriptor fd) throws IOException {
         try {
             Os.lseek(fd, 0, OsConstants.SEEK_CUR);
@@ -1800,9 +1756,9 @@
      * and make a single call rather than multiple calls for each attribute.
      */
     public void saveAttributes() throws IOException {
-        if (mIsRaw) {
+        if (mMimeType != IMAGE_TYPE_JPEG) {
             throw new UnsupportedOperationException(
-                    "ExifInterface does not support saving attributes on RAW formats.");
+                    "ExifInterface only supports saving attributes on JPEG formats.");
         }
         if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) {
             throw new UnsupportedOperationException(
@@ -1955,9 +1911,9 @@
             }
 
             ExifAttribute imageLengthAttribute =
-                    (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_LENGTH);
+                    (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_LENGTH);
             ExifAttribute imageWidthAttribute =
-                    (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_WIDTH);
+                    (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_WIDTH);
             if (imageLengthAttribute != null && imageWidthAttribute != null) {
                 int imageLength = imageLengthAttribute.getIntValue(mExifByteOrder);
                 int imageWidth = imageWidthAttribute.getIntValue(mExifByteOrder);
@@ -2226,9 +2182,9 @@
      *
      * @param inputStream The input stream that starts with the JPEG data.
      * @param jpegOffset The offset value in input stream for JPEG data.
-     * @param imageTypes The image type from which to retrieve metadata. Use IFD_TIFF_HINT for
-     *                   primary image, IFD_PREVIEW_HINT for preview image, and
-     *                   IFD_THUMBNAIL_HINT for thumbnail image.
+     * @param imageTypes The image type from which to retrieve metadata. Use IFD_TYPE_PRIMARY for
+     *                   primary image, IFD_TYPE_PREVIEW for preview image, and
+     *                   IFD_TYPE_THUMBNAIL for thumbnail image.
      * @throws IOException If the data contains invalid JPEG markers, offsets, or length values.
      */
     private void getJpegAttributes(InputStream inputStream, int jpegOffset, int imageType)
@@ -2329,7 +2285,7 @@
                     }
                     length = 0;
                     if (getAttribute(TAG_USER_COMMENT) == null) {
-                        mAttributes[IFD_EXIF_HINT].put(TAG_USER_COMMENT, ExifAttribute.createString(
+                        mAttributes[IFD_TYPE_EXIF].put(TAG_USER_COMMENT, ExifAttribute.createString(
                                 new String(bytes, ASCII)));
                     }
                     break;
@@ -2389,12 +2345,12 @@
         parseTiffHeaders(dataInputStream, exifBytes.length);
 
         // Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6.
-        readImageFileDirectory(dataInputStream, IFD_TIFF_HINT);
+        readImageFileDirectory(dataInputStream, IFD_TYPE_PRIMARY);
 
         // Update ImageLength/Width tags for all image data.
-        updateImageSizeValues(in, IFD_TIFF_HINT);
-        updateImageSizeValues(in, IFD_PREVIEW_HINT);
-        updateImageSizeValues(in, IFD_THUMBNAIL_HINT);
+        updateImageSizeValues(in, IFD_TYPE_PRIMARY);
+        updateImageSizeValues(in, IFD_TYPE_PREVIEW);
+        updateImageSizeValues(in, IFD_TYPE_THUMBNAIL);
 
         // Check if each image data is in valid position.
         validateImages(in);
@@ -2403,7 +2359,7 @@
             // PEF files contain a MakerNote data, which contains the data for ColorSpace tag.
             // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData()
             ExifAttribute makerNoteAttribute =
-                    (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
+                    (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
             if (makerNoteAttribute != null) {
                 // Create an ordered DataInputStream for MakerNote
                 ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
@@ -2414,13 +2370,13 @@
                 makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE);
 
                 // Read IFD data from MakerNote
-                readImageFileDirectory(makerNoteDataInputStream, PEF_HINT);
+                readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_PEF);
 
                 // Update ColorSpace tag
                 ExifAttribute colorSpaceAttribute =
-                        (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE);
+                        (ExifAttribute) mAttributes[IFD_TYPE_PEF].get(TAG_COLOR_SPACE);
                 if (colorSpaceAttribute != null) {
-                    mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute);
+                    mAttributes[IFD_TYPE_EXIF].put(TAG_COLOR_SPACE, colorSpaceAttribute);
                 }
             }
         }
@@ -2453,7 +2409,7 @@
         in.reset();
 
         // Retrieve JPEG image metadata
-        getJpegAttributes(in, rafJpegOffset, IFD_PREVIEW_HINT);
+        getJpegAttributes(in, rafJpegOffset, IFD_TYPE_PREVIEW);
 
         // Skip to CFA header offset.
         // A while loop is used because the skip method may not be able to skip the requested amount
@@ -2490,8 +2446,8 @@
                         ExifAttribute.createUShort(imageLength, mExifByteOrder);
                 ExifAttribute imageWidthAttribute =
                         ExifAttribute.createUShort(imageWidth, mExifByteOrder);
-                mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
-                mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
+                mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
+                mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
                 if (DEBUG) {
                     Log.d(TAG, "Updated to length: " + imageLength + ", width: " + imageWidth);
                 }
@@ -2520,7 +2476,7 @@
         // proprietary tags and therefore does not have offical documentation
         // See GetOlympusPreviewImage() in piex.cc & http://www.exiv2.org/tags-olympus.html
         ExifAttribute makerNoteAttribute =
-                (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
+                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
         if (makerNoteAttribute != null) {
             // Create an ordered DataInputStream for MakerNote
             ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
@@ -2542,18 +2498,18 @@
             }
 
             // Read IFD data from MakerNote
-            readImageFileDirectory(makerNoteDataInputStream, ORF_MAKER_NOTE_HINT);
+            readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_ORF_MAKER_NOTE);
 
             // Retrieve & update preview image offset & length values
             ExifAttribute imageLengthAttribute = (ExifAttribute)
-                    mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_START);
+                    mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_START);
             ExifAttribute bitsPerSampleAttribute = (ExifAttribute)
-                    mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_LENGTH);
+                    mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_LENGTH);
 
             if (imageLengthAttribute != null && bitsPerSampleAttribute != null) {
-                mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT,
+                mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT,
                         imageLengthAttribute);
-                mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+                mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
                         bitsPerSampleAttribute);
             }
 
@@ -2561,7 +2517,7 @@
             // Retrieve primary image length & width values
             // See piex.cc GetOlympusPreviewImage()
             ExifAttribute aspectFrameAttribute = (ExifAttribute)
-                    mAttributes[ORF_IMAGE_PROCESSING_HINT].get(TAG_ORF_ASPECT_FRAME);
+                    mAttributes[IFD_TYPE_ORF_IMAGE_PROCESSING].get(TAG_ORF_ASPECT_FRAME);
             if (aspectFrameAttribute != null) {
                 int[] aspectFrameValues = new int[4];
                 aspectFrameValues = (int[]) aspectFrameAttribute.getValue(mExifByteOrder);
@@ -2580,8 +2536,8 @@
                     ExifAttribute primaryImageLengthAttribute =
                             ExifAttribute.createUShort(primaryImageLength, mExifByteOrder);
 
-                    mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute);
-                    mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute);
+                    mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute);
+                    mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute);
                 }
             }
         }
@@ -2596,47 +2552,19 @@
 
         // Retrieve preview and/or thumbnail image data
         ExifAttribute jpgFromRawAttribute =
-                (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_JPG_FROM_RAW);
+                (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_JPG_FROM_RAW);
         if (jpgFromRawAttribute != null) {
-            getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_PREVIEW_HINT);
+            getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_TYPE_PREVIEW);
         }
 
         // Set ISO tag value if necessary
         ExifAttribute rw2IsoAttribute =
-                (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_ISO);
+                (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_ISO);
         ExifAttribute exifIsoAttribute =
-                (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_ISO_SPEED_RATINGS);
+                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_ISO_SPEED_RATINGS);
         if (rw2IsoAttribute != null && exifIsoAttribute == null) {
             // Place this attribute only if it doesn't exist
-            mAttributes[IFD_EXIF_HINT].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute);
-        }
-    }
-
-    // PEF is TIFF-based and contains 3 IFDs. It also contains a MakerNote data, which contains the
-    // ColorSpace tag data.
-    // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData()
-    private void getPefAttributes(InputStream in) throws IOException {
-        // Retrieve ColorSpace tag
-        ExifAttribute makerNoteAttribute =
-                (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
-        if (makerNoteAttribute != null) {
-            // Create an ordered DataInputStream for MakerNote
-            ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
-                    new ByteOrderAwarenessDataInputStream(makerNoteAttribute.bytes);
-            makerNoteDataInputStream.setByteOrder(mExifByteOrder);
-
-            // Seek to MakerNote data
-            makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE);
-
-            // Read IFD data from MakerNote
-            readImageFileDirectory(makerNoteDataInputStream, PEF_HINT);
-
-            // Update ColorSpace tag
-            ExifAttribute colorSpaceAttribute =
-                    (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE);
-            if (colorSpaceAttribute != null) {
-                mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute);
-            }
+            mAttributes[IFD_TYPE_EXIF].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute);
         }
     }
 
@@ -2754,25 +2682,25 @@
         // The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag.
         String valueOfDateTimeOriginal = getAttribute(TAG_DATETIME_ORIGINAL);
         if (valueOfDateTimeOriginal != null) {
-            mAttributes[IFD_TIFF_HINT].put(TAG_DATETIME,
+            mAttributes[IFD_TYPE_PRIMARY].put(TAG_DATETIME,
                     ExifAttribute.createString(valueOfDateTimeOriginal));
         }
 
         // Add the default value.
         if (getAttribute(TAG_IMAGE_WIDTH) == null) {
-            mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH,
+            mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH,
                     ExifAttribute.createULong(0, mExifByteOrder));
         }
         if (getAttribute(TAG_IMAGE_LENGTH) == null) {
-            mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH,
+            mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH,
                     ExifAttribute.createULong(0, mExifByteOrder));
         }
         if (getAttribute(TAG_ORIENTATION) == null) {
-            mAttributes[IFD_TIFF_HINT].put(TAG_ORIENTATION,
+            mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION,
                     ExifAttribute.createULong(0, mExifByteOrder));
         }
         if (getAttribute(TAG_LIGHT_SOURCE) == null) {
-            mAttributes[IFD_EXIF_HINT].put(TAG_LIGHT_SOURCE,
+            mAttributes[IFD_TYPE_EXIF].put(TAG_LIGHT_SOURCE,
                     ExifAttribute.createULong(0, mExifByteOrder));
         }
     }
@@ -2824,8 +2752,8 @@
     }
 
     // Reads image file directory, which is a tag group in EXIF.
-    private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint)
-            throws IOException {
+    private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream,
+            @IfdType int ifdType) throws IOException {
         if (dataInputStream.peek() + 2 > dataInputStream.mLength) {
             // Return if there is no data from the offset.
             return;
@@ -2850,12 +2778,12 @@
             long nextEntryOffset = dataInputStream.peek() + 4;
 
             // Look up a corresponding tag from tag number
-            ExifTag tag = (ExifTag) sExifTagMapsForReading[hint].get(tagNumber);
+            ExifTag tag = (ExifTag) sExifTagMapsForReading[ifdType].get(tagNumber);
 
             if (DEBUG) {
-                Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d, " +
-                        "numberOfComponents: %d", hint, tagNumber, tag != null ? tag.name : null,
-                        dataFormat, numberOfComponents));
+                Log.d(TAG, String.format("ifdType: %d, tagNumber: %d, tagName: %s, dataFormat: %d, "
+                        + "numberOfComponents: %d", ifdType, tagNumber,
+                        tag != null ? tag.name : null, dataFormat, numberOfComponents));
             }
 
             if (tag == null || dataFormat <= 0 ||
@@ -2882,7 +2810,8 @@
                     if (tag.name == TAG_MAKER_NOTE) {
                         // Save offset value for reading thumbnail
                         mOrfMakerNoteOffset = offset;
-                    } else if (hint == ORF_MAKER_NOTE_HINT && tag.name == TAG_ORF_THUMBNAIL_IMAGE) {
+                    } else if (ifdType == IFD_TYPE_ORF_MAKER_NOTE
+                            && tag.name == TAG_ORF_THUMBNAIL_IMAGE) {
                         // Retrieve & update values for thumbnail offset and length values for ORF
                         mOrfThumbnailOffset = offset;
                         mOrfThumbnailLength = numberOfComponents;
@@ -2894,10 +2823,10 @@
                         ExifAttribute jpegInterchangeFormatLengthAttribute =
                                 ExifAttribute.createULong(mOrfThumbnailLength, mExifByteOrder);
 
-                        mAttributes[IFD_THUMBNAIL_HINT].put(TAG_COMPRESSION, compressionAttribute);
-                        mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT,
+                        mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_COMPRESSION, compressionAttribute);
+                        mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT,
                                 jpegInterchangeFormatAttribute);
-                        mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+                        mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
                                 jpegInterchangeFormatLengthAttribute);
                     }
                 } else if (mMimeType == IMAGE_TYPE_RW2) {
@@ -2916,12 +2845,12 @@
             }
 
             // Recursively parse IFD when a IFD pointer tag appears.
-            int innerIfdHint = getIfdHintFromTagNumber(tagNumber);
+            Object nextIfdType = sExifPointerTagMap.get(tagNumber);
             if (DEBUG) {
-                Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount);
+                Log.d(TAG, "nextIfdType: " + nextIfdType + " byteCount: " + byteCount);
             }
 
-            if (innerIfdHint >= 0) {
+            if (nextIfdType != null) {
                 long offset = -1L;
                 // Get offset from data field
                 switch (dataFormat) {
@@ -2952,7 +2881,7 @@
                 }
                 if (offset > 0L && offset < dataInputStream.mLength) {
                     dataInputStream.seek(offset);
-                    readImageFileDirectory(dataInputStream, innerIfdHint);
+                    readImageFileDirectory(dataInputStream, (int) nextIfdType);
                 } else {
                     Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset);
                 }
@@ -2964,7 +2893,7 @@
             byte[] bytes = new byte[byteCount];
             dataInputStream.readFully(bytes);
             ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes);
-            mAttributes[hint].put(tag.name, attribute);
+            mAttributes[ifdType].put(tag.name, attribute);
 
             // DNG files have a DNG Version tag specifying the version of specifications that the
             // image file is following.
@@ -2998,11 +2927,11 @@
             // since the first IFD offset is at least 8.
             if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) {
                 dataInputStream.seek(nextIfdOffset);
-                if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
+                if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
                     // Do not overwrite thumbnail IFD data if it alreay exists.
-                    readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
-                } else if (mAttributes[IFD_PREVIEW_HINT].isEmpty()) {
-                    readImageFileDirectory(dataInputStream, IFD_PREVIEW_HINT);
+                    readImageFileDirectory(dataInputStream, IFD_TYPE_THUMBNAIL);
+                } else if (mAttributes[IFD_TYPE_PREVIEW].isEmpty()) {
+                    readImageFileDirectory(dataInputStream, IFD_TYPE_PREVIEW);
                 }
             }
         }
@@ -3037,7 +2966,7 @@
 
     // Sets thumbnail offset & length attributes based on JpegInterchangeFormat or StripOffsets tags
     private void setThumbnailData(InputStream in) throws IOException {
-        HashMap thumbnailData = mAttributes[IFD_THUMBNAIL_HINT];
+        HashMap thumbnailData = mAttributes[IFD_TYPE_THUMBNAIL];
 
         ExifAttribute compressionAttribute =
                 (ExifAttribute) thumbnailData.get(TAG_COMPRESSION);
@@ -3207,21 +3136,21 @@
     // Validate primary, preview, thumbnail image data by comparing image size
     private void validateImages(InputStream in) throws IOException {
         // Swap images based on size (primary > preview > thumbnail)
-        swapBasedOnImageSize(IFD_TIFF_HINT, IFD_PREVIEW_HINT);
-        swapBasedOnImageSize(IFD_TIFF_HINT, IFD_THUMBNAIL_HINT);
-        swapBasedOnImageSize(IFD_PREVIEW_HINT, IFD_THUMBNAIL_HINT);
+        swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_PREVIEW);
+        swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_THUMBNAIL);
+        swapBasedOnImageSize(IFD_TYPE_PREVIEW, IFD_TYPE_THUMBNAIL);
 
         // Check whether thumbnail image exists and whether preview image satisfies the thumbnail
         // image requirements
-        if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
-            if (isThumbnail(mAttributes[IFD_PREVIEW_HINT])) {
-                mAttributes[IFD_THUMBNAIL_HINT] = mAttributes[IFD_PREVIEW_HINT];
-                mAttributes[IFD_PREVIEW_HINT] = new HashMap();
+        if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
+            if (isThumbnail(mAttributes[IFD_TYPE_PREVIEW])) {
+                mAttributes[IFD_TYPE_THUMBNAIL] = mAttributes[IFD_TYPE_PREVIEW];
+                mAttributes[IFD_TYPE_PREVIEW] = new HashMap();
             }
         }
 
         // Check if the thumbnail image satisfies the thumbnail size requirements
-        if (!isThumbnail(mAttributes[IFD_THUMBNAIL_HINT])) {
+        if (!isThumbnail(mAttributes[IFD_TYPE_THUMBNAIL])) {
             Log.d(TAG, "No image meets the size requirements of a thumbnail image.");
         }
     }
@@ -3305,9 +3234,9 @@
                 if (newSubfileTypeValue == ORIGINAL_RESOLUTION_IMAGE) {
                     // Update only for the primary image (OriginalResolutionImage)
                     ExifAttribute pixelXDimAttribute =
-                            (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_X_DIMENSION);
+                            (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_X_DIMENSION);
                     ExifAttribute pixelYDimAttribute =
-                            (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_Y_DIMENSION);
+                            (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_Y_DIMENSION);
 
                     if (pixelXDimAttribute != null && pixelYDimAttribute != null) {
                         mAttributes[imageType].put(TAG_IMAGE_WIDTH, pixelXDimAttribute);
@@ -3320,16 +3249,6 @@
         }
     }
 
-    // Gets the corresponding IFD group index of the given tag number for writing Exif Tags.
-    private static int getIfdHintFromTagNumber(int tagNumber) {
-        for (int i = 0; i < EXIF_POINTER_TAG_HINTS.length; ++i) {
-            if (EXIF_POINTER_TAGS[i].number == tagNumber) {
-                return EXIF_POINTER_TAG_HINTS[i];
-            }
-        }
-        return -1;
-    }
-
     // Writes an Exif segment into the given output stream.
     private int writeExifSegment(ByteOrderAwarenessDataOutputStream dataOutputStream,
             int exifOffsetFromBeginning) throws IOException {
@@ -3346,33 +3265,33 @@
         removeAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name);
 
         // Remove null value tags.
-        for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            for (Object obj : mAttributes[hint].entrySet().toArray()) {
+        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+            for (Object obj : mAttributes[ifdType].entrySet().toArray()) {
                 final Map.Entry entry = (Map.Entry) obj;
                 if (entry.getValue() == null) {
-                    mAttributes[hint].remove(entry.getKey());
+                    mAttributes[ifdType].remove(entry.getKey());
                 }
             }
         }
 
         // Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
         // offset when there is one or more tags in the thumbnail IFD.
-        if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
-            mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name,
+        if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
+            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
                     ExifAttribute.createULong(0, mExifByteOrder));
         }
-        if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
-            mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name,
+        if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
+            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
                     ExifAttribute.createULong(0, mExifByteOrder));
         }
-        if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
-            mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name,
+        if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
+            mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name,
                     ExifAttribute.createULong(0, mExifByteOrder));
         }
         if (mHasThumbnail) {
-            mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
+            mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
                     ExifAttribute.createULong(0, mExifByteOrder));
-            mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
+            mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
                     ExifAttribute.createULong(mThumbnailLength, mExifByteOrder));
         }
 
@@ -3392,15 +3311,15 @@
 
         // Calculate IFD offsets.
         int position = 8;
-        for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            if (!mAttributes[hint].isEmpty()) {
-                ifdOffsets[hint] = position;
-                position += 2 + mAttributes[hint].size() * 12 + 4 + ifdDataSizes[hint];
+        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+            if (!mAttributes[ifdType].isEmpty()) {
+                ifdOffsets[ifdType] = position;
+                position += 2 + mAttributes[ifdType].size() * 12 + 4 + ifdDataSizes[ifdType];
             }
         }
         if (mHasThumbnail) {
             int thumbnailOffset = position;
-            mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
+            mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
                     ExifAttribute.createULong(thumbnailOffset, mExifByteOrder));
             mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset;
             position += mThumbnailLength;
@@ -3417,17 +3336,17 @@
         }
 
         // Update IFD pointer tags with the calculated offsets.
-        if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
-            mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name,
-                    ExifAttribute.createULong(ifdOffsets[IFD_EXIF_HINT], mExifByteOrder));
+        if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
+            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
+                    ExifAttribute.createULong(ifdOffsets[IFD_TYPE_EXIF], mExifByteOrder));
         }
-        if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
-            mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name,
-                    ExifAttribute.createULong(ifdOffsets[IFD_GPS_HINT], mExifByteOrder));
+        if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
+            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
+                    ExifAttribute.createULong(ifdOffsets[IFD_TYPE_GPS], mExifByteOrder));
         }
-        if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
-            mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(
-                    ifdOffsets[IFD_INTEROPERABILITY_HINT], mExifByteOrder));
+        if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
+            mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(
+                    ifdOffsets[IFD_TYPE_INTEROPERABILITY], mExifByteOrder));
         }
 
         // Write TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1.
@@ -3440,17 +3359,18 @@
         dataOutputStream.writeUnsignedInt(IFD_OFFSET);
 
         // Write IFD groups. See JEITA CP-3451C Section 4.5.8. Figure 9.
-        for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            if (!mAttributes[hint].isEmpty()) {
+        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+            if (!mAttributes[ifdType].isEmpty()) {
                 // See JEITA CP-3451C Section 4.6.2: IFD structure.
                 // Write entry count
-                dataOutputStream.writeUnsignedShort(mAttributes[hint].size());
+                dataOutputStream.writeUnsignedShort(mAttributes[ifdType].size());
 
                 // Write entry info
-                int dataOffset = ifdOffsets[hint] + 2 + mAttributes[hint].size() * 12 + 4;
-                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+                int dataOffset = ifdOffsets[ifdType] + 2 + mAttributes[ifdType].size() * 12 + 4;
+                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) {
                     // Convert tag name to tag number.
-                    final ExifTag tag = (ExifTag) sExifTagMapsForWriting[hint].get(entry.getKey());
+                    final ExifTag tag =
+                            (ExifTag) sExifTagMapsForWriting[ifdType].get(entry.getKey());
                     final int tagNumber = tag.number;
                     final ExifAttribute attribute = (ExifAttribute) entry.getValue();
                     final int size = attribute.size();
@@ -3475,14 +3395,14 @@
                 // Write the next offset. It writes the offset of thumbnail IFD if there is one or
                 // more tags in the thumbnail IFD when the current IFD is the primary image TIFF
                 // IFD; Otherwise 0.
-                if (hint == 0 && !mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
-                    dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_THUMBNAIL_HINT]);
+                if (ifdType == 0 && !mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
+                    dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_TYPE_THUMBNAIL]);
                 } else {
                     dataOutputStream.writeUnsignedInt(0);
                 }
 
                 // Write values of data field exceeding 4 bytes after the next offset.
-                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) {
                     ExifAttribute attribute = (ExifAttribute) entry.getValue();
 
                     if (attribute.bytes.length > 4) {
@@ -3809,9 +3729,9 @@
     }
 
     // Swaps image data based on image size
-    private void swapBasedOnImageSize(int firstImageHint, int secondImageHint)
+    private void swapBasedOnImageSize(@IfdType int firstIfdType, @IfdType int secondIfdType)
             throws IOException {
-        if (mAttributes[firstImageHint].isEmpty() || mAttributes[secondImageHint].isEmpty()) {
+        if (mAttributes[firstIfdType].isEmpty() || mAttributes[secondIfdType].isEmpty()) {
             if (DEBUG) {
                 Log.d(TAG, "Cannot perform swap since only one image data exists");
             }
@@ -3819,13 +3739,13 @@
         }
 
         ExifAttribute firstImageLengthAttribute =
-                (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_LENGTH);
+                (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_LENGTH);
         ExifAttribute firstImageWidthAttribute =
-                (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_WIDTH);
+                (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_WIDTH);
         ExifAttribute secondImageLengthAttribute =
-                (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_LENGTH);
+                (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_LENGTH);
         ExifAttribute secondImageWidthAttribute =
-                (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_WIDTH);
+                (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_WIDTH);
 
         if (firstImageLengthAttribute == null || firstImageWidthAttribute == null) {
             if (DEBUG) {
@@ -3843,9 +3763,9 @@
 
             if (firstImageLengthValue < secondImageLengthValue &&
                     firstImageWidthValue < secondImageWidthValue) {
-                HashMap tempMap = mAttributes[firstImageHint];
-                mAttributes[firstImageHint] = mAttributes[secondImageHint];
-                mAttributes[secondImageHint] = tempMap;
+                HashMap tempMap = mAttributes[firstIfdType];
+                mAttributes[firstIfdType] = mAttributes[secondIfdType];
+                mAttributes[secondIfdType] = tempMap;
             }
         }
     }
@@ -3864,12 +3784,4 @@
         }
         return false;
     }
-
-    // JNI methods for RAW formats.
-    private static native void nativeInitRaw();
-    private static native byte[] nativeGetThumbnailFromAsset(
-            long asset, int thumbnailOffset, int thumbnailLength);
-    private static native HashMap nativeGetRawAttributesFromAsset(long asset);
-    private static native HashMap nativeGetRawAttributesFromFileDescriptor(FileDescriptor fd);
-    private static native HashMap nativeGetRawAttributesFromInputStream(InputStream in);
 }
\ No newline at end of file
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index fbc8615..4c49f67 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -226,10 +226,12 @@
                 ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair(
                                                     OsConstants.SOCK_SEQPACKET);
                 MidiInputPort inputPort = new MidiInputPort(pair[0], portNumber);
-                // Configure the server-side socket in non-blocking mode to avoid stalling
-                // the entire MIDI framework if client app code gets stuck inside 'onSend'
-                // handler.
-                IoUtils.setBlocking(pair[0].getFileDescriptor(), false);
+                // Undo the default blocking-mode of the server-side socket for
+                // physical devices to avoid stalling the Java device handler if
+                // client app code gets stuck inside 'onSend' handler.
+                if (mDeviceInfo.getType() != MidiDeviceInfo.TYPE_VIRTUAL) {
+                    IoUtils.setBlocking(pair[0].getFileDescriptor(), false);
+                }
                 MidiDispatcher dispatcher = mOutputPortDispatchers[portNumber];
                 synchronized (dispatcher) {
                     dispatcher.getSender().connect(inputPort);
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 2c28a10..dcd5057 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -3,7 +3,6 @@
 
 LOCAL_SRC_FILES:= \
     android_media_AmrInputStream.cpp \
-    android_media_ExifInterface.cpp \
     android_media_ImageWriter.cpp \
     android_media_ImageReader.cpp \
     android_media_MediaCrypto.cpp \
diff --git a/media/jni/android_media_ExifInterface.cpp b/media/jni/android_media_ExifInterface.cpp
deleted file mode 100644
index 10b31706..0000000
--- a/media/jni/android_media_ExifInterface.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright 2016 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 LOG_NDEBUG 0
-#define LOG_TAG "ExifInterface_JNI"
-
-#include "android_media_Utils.h"
-
-#include "android/graphics/CreateJavaOutputStreamAdaptor.h"
-#include "src/piex_types.h"
-#include "src/piex.h"
-
-#include <jni.h>
-#include <JNIHelp.h>
-#include <androidfw/Asset.h>
-#include <android_runtime/AndroidRuntime.h>
-#include <android/graphics/Utils.h>
-#include <nativehelper/ScopedLocalRef.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/KeyedVector.h>
-
-// ----------------------------------------------------------------------------
-
-using namespace android;
-
-static const char kJpegSignatureChars[] = {(char)0xff, (char)0xd8, (char)0xff};
-static const int kJpegSignatureSize = 3;
-
-#define FIND_CLASS(var, className) \
-    var = env->FindClass(className); \
-    LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
-    var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! var, "Unable to find method " fieldName);
-
-struct HashMapFields {
-    jmethodID init;
-    jmethodID put;
-};
-
-struct fields_t {
-    HashMapFields hashMap;
-    jclass hashMapClassId;
-};
-
-static fields_t gFields;
-
-static jobject KeyedVectorToHashMap(JNIEnv *env, KeyedVector<String8, String8> const &map) {
-    jclass clazz = gFields.hashMapClassId;
-    jobject hashMap = env->NewObject(clazz, gFields.hashMap.init);
-    for (size_t i = 0; i < map.size(); ++i) {
-        jstring jkey = env->NewStringUTF(map.keyAt(i).string());
-        jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
-        env->CallObjectMethod(hashMap, gFields.hashMap.put, jkey, jvalue);
-        env->DeleteLocalRef(jkey);
-        env->DeleteLocalRef(jvalue);
-    }
-    return hashMap;
-}
-
-extern "C" {
-
-// -------------------------- ExifInterface methods ---------------------------
-
-static void ExifInterface_initRaw(JNIEnv *env) {
-    jclass clazz;
-    FIND_CLASS(clazz, "java/util/HashMap");
-    gFields.hashMapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
-
-    GET_METHOD_ID(gFields.hashMap.init, clazz, "<init>", "()V");
-    GET_METHOD_ID(gFields.hashMap.put, clazz, "put",
-                  "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-}
-
-static bool is_asset_stream(const SkStream& stream) {
-    return stream.hasLength() && stream.hasPosition();
-}
-
-static jobject ExifInterface_getThumbnailFromAsset(
-        JNIEnv* env, jclass /* clazz */, jlong jasset, jint jthumbnailOffset,
-        jint jthumbnailLength) {
-    Asset* asset = reinterpret_cast<Asset*>(jasset);
-    std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset));
-
-    std::unique_ptr<jbyte[]> thumbnailData(new jbyte[(int)jthumbnailLength]);
-    if (thumbnailData.get() == NULL) {
-        ALOGI("No memory to get thumbnail");
-        return NULL;
-    }
-
-    // Do not know the current offset. So rewind it.
-    stream->rewind();
-
-    // Read thumbnail.
-    stream->skip((int)jthumbnailOffset);
-    stream->read((void*)thumbnailData.get(), (int)jthumbnailLength);
-
-    // Copy to the byte array.
-    jbyteArray byteArray = env->NewByteArray(jthumbnailLength);
-    env->SetByteArrayRegion(byteArray, 0, jthumbnailLength, thumbnailData.get());
-    return byteArray;
-}
-
-static jobject getRawAttributes(JNIEnv* env, SkStream* stream, bool returnThumbnail) {
-    std::unique_ptr<SkStream> streamDeleter(stream);
-
-    std::unique_ptr<::piex::StreamInterface> piexStream;
-    if (is_asset_stream(*stream)) {
-        piexStream.reset(new AssetStream(streamDeleter.release()));
-    } else {
-        piexStream.reset(new BufferedStream(streamDeleter.release()));
-    }
-
-    piex::PreviewImageData image_data;
-
-    if (!GetExifFromRawImage(piexStream.get(), String8("[piex stream]"), image_data)) {
-        return NULL;
-    }
-
-    KeyedVector<String8, String8> map;
-
-    if (image_data.thumbnail.length > 0
-            && image_data.thumbnail.format == ::piex::Image::kJpegCompressed) {
-        map.add(String8("HasThumbnail"), String8("true"));
-        map.add(String8("ThumbnailOffset"), String8::format("%d", image_data.thumbnail.offset));
-        map.add(String8("ThumbnailLength"), String8::format("%d", image_data.thumbnail.length));
-    } else {
-        map.add(String8("HasThumbnail"), String8("false"));
-    }
-
-    map.add(
-            String8("Orientation"),
-            String8::format("%u", image_data.exif_orientation));
-    map.add(
-            String8("ImageWidth"),
-            String8::format("%u", image_data.full_width));
-    map.add(
-            String8("ImageLength"),
-            String8::format("%u", image_data.full_height));
-
-    // Current PIEX does not have LightSource information while JPEG version of
-    // EXIFInterface always declares the light source field. For the
-    // compatibility, it provides the default value of the light source field.
-    map.add(String8("LightSource"), String8("0"));
-
-    if (!image_data.maker.empty()) {
-        map.add(String8("Make"), String8(image_data.maker.c_str()));
-    }
-
-    if (!image_data.model.empty()) {
-        map.add(String8("Model"), String8(image_data.model.c_str()));
-    }
-
-    if (!image_data.date_time.empty()) {
-        map.add(String8("DateTime"), String8(image_data.date_time.c_str()));
-    }
-
-    if (image_data.iso) {
-        map.add(
-                String8("ISOSpeedRatings"),
-                String8::format("%u", image_data.iso));
-    }
-
-    if (image_data.exposure_time.numerator != 0
-            && image_data.exposure_time.denominator != 0) {
-        double exposureTime =
-            (double)image_data.exposure_time.numerator
-            / image_data.exposure_time.denominator;
-
-        const char* format;
-        if (exposureTime < 0.01) {
-            format = "%6.4f";
-        } else {
-            format = "%5.3f";
-        }
-        map.add(String8("ExposureTime"), String8::format(format, exposureTime));
-    }
-
-    if (image_data.fnumber.numerator != 0
-            && image_data.fnumber.denominator != 0) {
-        double fnumber =
-            (double)image_data.fnumber.numerator
-            / image_data.fnumber.denominator;
-        map.add(String8("FNumber"), String8::format("%5.3f", fnumber));
-    }
-
-    if (image_data.focal_length.numerator != 0
-            && image_data.focal_length.denominator != 0) {
-        map.add(
-                String8("FocalLength"),
-                String8::format(
-                        "%u/%u",
-                        image_data.focal_length.numerator,
-                        image_data.focal_length.denominator));
-    }
-
-    if (image_data.gps.is_valid) {
-        if (image_data.gps.latitude[0].denominator != 0
-                && image_data.gps.latitude[1].denominator != 0
-                && image_data.gps.latitude[2].denominator != 0) {
-            map.add(
-                    String8("GPSLatitude"),
-                    String8::format(
-                            "%u/%u,%u/%u,%u/%u",
-                            image_data.gps.latitude[0].numerator,
-                            image_data.gps.latitude[0].denominator,
-                            image_data.gps.latitude[1].numerator,
-                            image_data.gps.latitude[1].denominator,
-                            image_data.gps.latitude[2].numerator,
-                            image_data.gps.latitude[2].denominator));
-        }
-
-        if (image_data.gps.latitude_ref) {
-            char str[2];
-            str[0] = image_data.gps.latitude_ref;
-            str[1] = 0;
-            map.add(String8("GPSLatitudeRef"), String8(str));
-        }
-
-        if (image_data.gps.longitude[0].denominator != 0
-                && image_data.gps.longitude[1].denominator != 0
-                && image_data.gps.longitude[2].denominator != 0) {
-            map.add(
-                    String8("GPSLongitude"),
-                    String8::format(
-                            "%u/%u,%u/%u,%u/%u",
-                            image_data.gps.longitude[0].numerator,
-                            image_data.gps.longitude[0].denominator,
-                            image_data.gps.longitude[1].numerator,
-                            image_data.gps.longitude[1].denominator,
-                            image_data.gps.longitude[2].numerator,
-                            image_data.gps.longitude[2].denominator));
-        }
-
-        if (image_data.gps.longitude_ref) {
-            char str[2];
-            str[0] = image_data.gps.longitude_ref;
-            str[1] = 0;
-            map.add(String8("GPSLongitudeRef"), String8(str));
-        }
-
-        if (image_data.gps.altitude.denominator != 0) {
-            map.add(
-                    String8("GPSAltitude"),
-                    String8::format("%u/%u",
-                            image_data.gps.altitude.numerator,
-                            image_data.gps.altitude.denominator));
-
-            map.add(
-                    String8("GPSAltitudeRef"),
-                    String8(image_data.gps.altitude_ref ? "1" : "0"));
-        }
-
-        if (image_data.gps.time_stamp[0].denominator != 0
-                && image_data.gps.time_stamp[1].denominator != 0
-                && image_data.gps.time_stamp[2].denominator != 0) {
-            map.add(
-                    String8("GPSTimeStamp"),
-                    String8::format(
-                            "%02u:%02u:%02u",
-                            image_data.gps.time_stamp[0].numerator
-                            / image_data.gps.time_stamp[0].denominator,
-                            image_data.gps.time_stamp[1].numerator
-                            / image_data.gps.time_stamp[1].denominator,
-                            image_data.gps.time_stamp[2].numerator
-                            / image_data.gps.time_stamp[2].denominator));
-        }
-
-        if (!image_data.gps.date_stamp.empty()) {
-            map.add(
-                    String8("GPSDateStamp"),
-                    String8(image_data.gps.date_stamp.c_str()));
-        }
-    }
-
-    jobject hashMap = KeyedVectorToHashMap(env, map);
-
-    if (returnThumbnail) {
-        std::unique_ptr<jbyte[]> thumbnailData(new jbyte[image_data.thumbnail.length]);
-        if (thumbnailData.get() == NULL) {
-            ALOGE("No memory to parse a thumbnail");
-            return NULL;
-        }
-        jbyteArray jthumbnailByteArray = env->NewByteArray(image_data.thumbnail.length);
-        if (jthumbnailByteArray == NULL) {
-            ALOGE("No memory to parse a thumbnail");
-            return NULL;
-        }
-        piexStream.get()->GetData(image_data.thumbnail.offset, image_data.thumbnail.length,
-                (uint8_t*)thumbnailData.get());
-        env->SetByteArrayRegion(
-                jthumbnailByteArray, 0, image_data.thumbnail.length, thumbnailData.get());
-        jstring jkey = env->NewStringUTF(String8("ThumbnailData"));
-        env->CallObjectMethod(hashMap, gFields.hashMap.put, jkey, jthumbnailByteArray);
-        env->DeleteLocalRef(jkey);
-        env->DeleteLocalRef(jthumbnailByteArray);
-    }
-    return hashMap;
-}
-
-static jobject ExifInterface_getRawAttributesFromAsset(
-        JNIEnv* env, jclass /* clazz */, jlong jasset) {
-    std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]);
-    if (jpegSignature.get() == NULL) {
-        ALOGE("No enough memory to parse");
-        return NULL;
-    }
-
-    Asset* asset = reinterpret_cast<Asset*>(jasset);
-    std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset));
-
-    if (stream.get()->read(jpegSignature.get(), kJpegSignatureSize) != kJpegSignatureSize) {
-        // Rewind the stream.
-        stream.get()->rewind();
-
-        ALOGI("Corrupted image.");
-        return NULL;
-    }
-
-    // Rewind the stream.
-    stream.get()->rewind();
-
-    if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) {
-        ALOGI("Should be a JPEG stream.");
-        return NULL;
-    }
-
-    // Try to parse from the given stream.
-    jobject result = getRawAttributes(env, stream.get(), false);
-
-    // Rewind the stream for the chance to read JPEG.
-    if (result == NULL) {
-        stream.get()->rewind();
-    }
-    return result;
-}
-
-static jobject ExifInterface_getRawAttributesFromFileDescriptor(
-        JNIEnv* env, jclass /* clazz */, jobject jfileDescriptor) {
-    std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]);
-    if (jpegSignature.get() == NULL) {
-        ALOGE("No enough memory to parse");
-        return NULL;
-    }
-
-    int fd = jniGetFDFromFileDescriptor(env, jfileDescriptor);
-    if (fd < 0) {
-        ALOGI("Invalid file descriptor");
-        return NULL;
-    }
-
-    // Restore the file descriptor's offset on exiting this function.
-    AutoFDSeek autoRestore(fd);
-
-    int dupFd = dup(fd);
-
-    FILE* file = fdopen(dupFd, "r");
-    if (file == NULL) {
-        ALOGI("Failed to open the file descriptor");
-        return NULL;
-    }
-
-    if (fgets(jpegSignature.get(), kJpegSignatureSize, file) == NULL) {
-        ALOGI("Corrupted image.");
-        return NULL;
-    }
-
-    if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) {
-        ALOGI("Should be a JPEG stream.");
-        return NULL;
-    }
-
-    // Rewind the file descriptor.
-    fseek(file, 0L, SEEK_SET);
-
-    std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file,
-                SkFILEStream::kCallerPasses_Ownership));
-    return getRawAttributes(env, fileStream.get(), false);
-}
-
-static jobject ExifInterface_getRawAttributesFromInputStream(
-        JNIEnv* env, jclass /* clazz */, jobject jinputStream) {
-    jbyteArray byteArray = env->NewByteArray(8*1024);
-    ScopedLocalRef<jbyteArray> scoper(env, byteArray);
-    std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, jinputStream, scoper.get()));
-    return getRawAttributes(env, stream.get(), true);
-}
-
-} // extern "C"
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gMethods[] = {
-    { "nativeInitRaw", "()V", (void *)ExifInterface_initRaw },
-    { "nativeGetThumbnailFromAsset", "(JII)[B", (void *)ExifInterface_getThumbnailFromAsset },
-    { "nativeGetRawAttributesFromAsset", "(J)Ljava/util/HashMap;",
-      (void*)ExifInterface_getRawAttributesFromAsset },
-    { "nativeGetRawAttributesFromFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/util/HashMap;",
-      (void*)ExifInterface_getRawAttributesFromFileDescriptor },
-    { "nativeGetRawAttributesFromInputStream", "(Ljava/io/InputStream;)Ljava/util/HashMap;",
-      (void*)ExifInterface_getRawAttributesFromInputStream },
-};
-
-int register_android_media_ExifInterface(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(
-            env,
-            "android/media/ExifInterface",
-            gMethods,
-            NELEM(gMethods));
-}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2fb1a3b..ecf733f 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1090,7 +1090,6 @@
     return AndroidRuntime::registerNativeMethods(env,
                 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
 }
-extern int register_android_media_ExifInterface(JNIEnv *env);
 extern int register_android_media_ImageReader(JNIEnv *env);
 extern int register_android_media_ImageWriter(JNIEnv *env);
 extern int register_android_media_Crypto(JNIEnv *env);
@@ -1222,11 +1221,6 @@
         goto bail;
     }
 
-    if (register_android_media_ExifInterface(env) < 0) {
-        ALOGE("ERROR: ExifInterface native registration failed");
-        goto bail;
-    }
-
     /* success -- return valid version number */
     result = JNI_VERSION_1_4;
 
diff --git a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
index 3c5dd37..8af7de6 100644
--- a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
+++ b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
@@ -90,8 +90,8 @@
         <item>0.0040</item>
         <item>0.0</item>
         <item>442/100</item>
-        <item>0/1</item>
-        <item>0</item>
+        <item />
+        <item />
         <item>1970:01:17</item>
         <item>53/1,50/1,423/100</item>
         <item>N</item>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
index 0cc15451..cdd4065 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -252,6 +252,7 @@
         if (stringValue != null) {
             stringValue = stringValue.trim();
         }
+        stringValue = (stringValue == "") ? null : stringValue;
 
         assertEquals(expectedValue, stringValue);
     }
diff --git a/packages/Keyguard/res/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml
index 568d82a..a338165 100644
--- a/packages/Keyguard/res/values-af/strings.xml
+++ b/packages/Keyguard/res/values-af/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kaart is gesluit."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kaart is PUK-geslote."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ontsluit tans SIM-kaart…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Patroon ontsluit."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN ontsluit."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Wagwoord ontsluit."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Patroonarea."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Sleep-area."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-area"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-PIN-area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-PUK-area"</string>
diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml
index 68e9ff3..67fdc32 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ሲም ካርድ ተዘግቷል።"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ሲም ካርድ በፒዩኬ ተዘግቷል።"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ሲም ካርዱን በመክፈት ላይ…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"በስርዓተ-ጥለት መክፈት።"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"በፒን መክፈት።"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"በይለፍ ቃል መክፈት።"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"የስርዓተ-ጥለት አካባቢ።"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"የማንሸራተቻ አካባቢ።"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"የፒን አካባቢ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"የሲም ፒን አካባቢ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"የሲም PUK አካባቢ"</string>
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index 09b78e4..8438699 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"‏شريحة SIM مؤمّنة."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"‏شريحة SIM مؤمّنة بكود PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"‏جارٍ إلغاء تأمين شريحة SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"إلغاء القفل باستخدام النقش."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"‏إلغاء القفل باستخدام رمز PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"إلغاء القفل باستخدام كلمة المرور."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"منطقة النقش."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"منطقة التمرير."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"منطقة رقم التعريف الشخصي"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"‏منطقة رقم التعريف الشخصي لبطاقة SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"‏منطقة PUK لبطاقة SIM"</string>
diff --git a/packages/Keyguard/res/values-az-rAZ/strings.xml b/packages/Keyguard/res/values-az-rAZ/strings.xml
index a8a1155..c7a8091 100644
--- a/packages/Keyguard/res/values-az-rAZ/strings.xml
+++ b/packages/Keyguard/res/values-az-rAZ/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kart kilidlənib."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SİM kart PUK ilə kilidlənib."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SİM kartın kilidi açılır..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Kild açma modeli."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin kilid açması."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Şifrə kilidi."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Model sahəsi."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Sürüşdürmə sahəsi."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN sahəsi"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN sahəsi"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK sahəsi"</string>
diff --git a/packages/Keyguard/res/values-b+sr+Latn/strings.xml b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
index 22dc059..570f4bc 100644
--- a/packages/Keyguard/res/values-b+sr+Latn/strings.xml
+++ b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica je zaključana PUK kodom."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Otključavanje šablonom."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje PIN-om."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje lozinkom."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblast šablona."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast prevlačenja."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblast za PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblast za PIN za SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblast za PUK za SIM"</string>
diff --git a/packages/Keyguard/res/values-be-rBY/strings.xml b/packages/Keyguard/res/values-be-rBY/strings.xml
index ca6a476..f357961 100644
--- a/packages/Keyguard/res/values-be-rBY/strings.xml
+++ b/packages/Keyguard/res/values-be-rBY/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта заблакiраваная."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карта заблакiравана PUK-кодам."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Разблакiраванне SIM-карты..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Узор разблакiроўкі."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код разблакiроўкі."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль разблакiроўкі."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Вобласць узора."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Вобласць слайда."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Поле для PIN-кода"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Поле для PIN-кода SIM-карты"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Поле для PUK-кода SIM-карты"</string>
diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml
index 7eb2dbd..988e97f 100644
--- a/packages/Keyguard/res/values-bg/strings.xml
+++ b/packages/Keyguard/res/values-bg/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картата е заключена."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картата е заключена с PUK код."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картата се отключва…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Отключване с фигура."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Отключване с ПИН код."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Отключване с парола."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област на фигурата."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област на плъзгане."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Област за ПИН кода"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Област за ПИН кода на SIM картата"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Област за PUK кода на SIM картата"</string>
diff --git a/packages/Keyguard/res/values-bn-rBD/strings.xml b/packages/Keyguard/res/values-bn-rBD/strings.xml
index 7a33e21..1a2a8dd 100644
--- a/packages/Keyguard/res/values-bn-rBD/strings.xml
+++ b/packages/Keyguard/res/values-bn-rBD/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"সিম কার্ড লক করা আছে৷"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"সিম কার্ডটি PUK কোড দিয়ে লক করা আছে৷"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"সিম কার্ড আনলক করা হচ্ছে…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"প্যাটার্ন দিয়ে আনলক৷"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"পিন দিয়ে আনলক৷"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"পাসওয়ার্ড দিয়ে আনলক৷"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"প্যাটার্ন এলাকা৷"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"স্লাইড করার এলাকা৷"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"পিন অঞ্চল"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM পিন অঞ্চল"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK অঞ্চল"</string>
diff --git a/packages/Keyguard/res/values-bs-rBA/strings.xml b/packages/Keyguard/res/values-bs-rBA/strings.xml
index 3c3af7b..b8ff2a9 100644
--- a/packages/Keyguard/res/values-bs-rBA/strings.xml
+++ b/packages/Keyguard/res/values-bs-rBA/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica je zaključana PUK kodom."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Otključavanje uzorkom."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje pinom."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje lozinkom."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Uzorak oblasti."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast za pomjeranje klizača."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Prostor za PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Prostor za SIM PIN"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Prostor za SIM PUK"</string>
diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml
index b542866..9207e0e 100644
--- a/packages/Keyguard/res/values-ca/strings.xml
+++ b/packages/Keyguard/res/values-ca/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La targeta SIM està bloquejada."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La targeta SIM està bloquejada pel PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"S\'està desbloquejant la targeta SIM..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueig mitjançant patró"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueig mitjançant PIN"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueig mitjançant contrasenya"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Àrea de patró"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Àrea per lliscar el dit"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona del PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona del PIN de la SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona del PUK de la SIM"</string>
diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml
index b310323..aa7115d 100644
--- a/packages/Keyguard/res/values-cs/strings.xml
+++ b/packages/Keyguard/res/values-cs/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta je zablokována."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta je zablokována pomocí kódu PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odblokování SIM karty…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odemknutí gestem."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odemknutí kódem PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odemknutí heslem."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblast pro zadání bezpečnostního gesta."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast pro přejetí prstem."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblast kódu PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblast kódu PIN SIM karty"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblast kódu PUK SIM karty"</string>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index b46b536..ebea6ee 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet er låst."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kort er låst med PUK-koden."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kortet låses op…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås op med mønster."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås op med pinkode."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås op med adgangskode."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Strygeområde."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Område for pinkoden"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Område for pinkoden til simkortet"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Område for PUK-koden til simkortet"</string>
diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml
index ae731c3..a519ce8 100644
--- a/packages/Keyguard/res/values-de/strings.xml
+++ b/packages/Keyguard/res/values-de/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-Karte ist gesperrt."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-Karte wird entsperrt…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Entsperrung mit Muster"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Entsperrung mit PIN"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Entsperrung mit Passwort"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bereich für Muster"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bereich für Fingerbewegung"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-Bereich"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-PIN-Bereich"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-PUK-Bereich"</string>
diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml
index c54a7fc..d969266 100644
--- a/packages/Keyguard/res/values-el/strings.xml
+++ b/packages/Keyguard/res/values-el/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Η κάρτα SIM είναι κλειδωμένη."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Η κάρτα SIM είναι κλειδωμένη με κωδικό PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ξεκλείδωμα κάρτας SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ξεκλείδωμα μοτίβου."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ξεκλείδωμα κωδικού ασφαλείας"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ξεκλείδωμα κωδικού πρόσβασης."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Περιοχή μοτίβου."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Περιοχή ολίσθησης"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Περιοχή PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Περιοχή PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Περιοχή PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-en-rAU/strings.xml b/packages/Keyguard/res/values-en-rAU/strings.xml
index e885166..9ecd979 100644
--- a/packages/Keyguard/res/values-en-rAU/strings.xml
+++ b/packages/Keyguard/res/values-en-rAU/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string>
diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml
index e885166..9ecd979 100644
--- a/packages/Keyguard/res/values-en-rGB/strings.xml
+++ b/packages/Keyguard/res/values-en-rGB/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string>
diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml
index e885166..9ecd979 100644
--- a/packages/Keyguard/res/values-en-rIN/strings.xml
+++ b/packages/Keyguard/res/values-en-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string>
diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml
index df0db2d..61f5c0d 100644
--- a/packages/Keyguard/res/values-es-rUS/strings.xml
+++ b/packages/Keyguard/res/values-es-rUS/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La tarjeta SIM está bloqueada."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La tarjeta SIM está bloqueada por código PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarjeta SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslizamiento"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área de PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área de PIN de SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área de PUK de SIM"</string>
diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml
index 6061b78..3ef737c 100644
--- a/packages/Keyguard/res/values-es/strings.xml
+++ b/packages/Keyguard/res/values-es/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La tarjeta SIM está bloqueada."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La tarjeta SIM está bloqueada con el código PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarjeta SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área para deslizar"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área de PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área de PIN de SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área de PUK de SIM"</string>
diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml
index 78ae3ca..47b6332 100644
--- a/packages/Keyguard/res/values-et-rEE/strings.xml
+++ b/packages/Keyguard/res/values-et-rEE/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kaart on lukus."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kaart on PUK-lukus."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kaardi avamine ..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mustriga avamine."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-koodiga avamine."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parooliga avamine."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mustri ala."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Lohistamisala."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-koodi ala"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-kaardi PIN-koodi ala"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-kaardi PUK-koodi ala"</string>
diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml
index 7855b16..5f4abce 100644
--- a/packages/Keyguard/res/values-eu-rES/strings.xml
+++ b/packages/Keyguard/res/values-eu-rES/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM txartela blokeatuta dago."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM txartela PUK bidez blokeatuta dago."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM txartela desblokeatzen…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ereduaren bidez desblokeatzea."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN kodearen bidez desblokeatzea."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Pasahitzaren bidez desblokeatzea."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Eredua marrazteko eremua."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Hatza lerratzeko eremua."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN kodearen eremua"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM txartelaren PIN kodearen eremua"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM txartelaren PUK kodearen eremua"</string>
diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml
index 39fd460..40952e2 100644
--- a/packages/Keyguard/res/values-fa/strings.xml
+++ b/packages/Keyguard/res/values-fa/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"سیم کارت قفل شد."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"‏سیم کارت با PUK قفل شده است."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"درحال بازگشایی قفل سیم کارت..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"باز کردن قفل با الگو."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"باز کردن قفل با پین."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"باز کردن قفل با گذرواژه."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ناحیه الگو."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ناحیه کشیدن انگشت روی صفحه."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"قسمت پین"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"قسمت پین سیم‌کارت"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"‏قسمت PUK سیم‌کارت"</string>
diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml
index 7a0c00f..a1b96ca 100644
--- a/packages/Keyguard/res/values-fi/strings.xml
+++ b/packages/Keyguard/res/values-fi/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortti on lukittu."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortti on PUK-lukittu."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kortin lukitusta poistetaan…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lukituksen poisto salasanalla."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lukituksen poisto PIN-koodilla."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lukituksen poisto salasanalla."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kuvioalue."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Liu\'utusalue."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-koodin alue"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-kortin PIN-koodin alue"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-kortin PUK-koodin alue"</string>
diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml
index 9bc2456..d920415 100644
--- a/packages/Keyguard/res/values-fr-rCA/strings.xml
+++ b/packages/Keyguard/res/values-fr-rCA/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La carte SIM est verrouillée."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La carte SIM est verrouillée par clé PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Déverrouillage de la carte SIM en cours…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Déverrouillage par schéma"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Déverrouillage par NIP"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Déverrouillage par mot de passe"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zone du schéma"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zone où faire glisser votre doigt sur l\'écran"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zone du NIP"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zone du NIP de la carte SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zone du code PUK de la carte SIM"</string>
diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml
index ecb2575..8615b99 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La carte SIM est verrouillée."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La carte SIM est verrouillée par clé PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Déverrouillage de la carte SIM en cours…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Déverrouillage par schéma"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Déverrouillage par code PIN"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Déverrouillage par mot de passe"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zone du schéma"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zone où faire glisser votre doigt sur l\'écran"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Champ du code PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Champ du code PIN de la carte SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Champ du code PUK de la carte SIM"</string>
diff --git a/packages/Keyguard/res/values-gl-rES/strings.xml b/packages/Keyguard/res/values-gl-rES/strings.xml
index 382dd7b..a894fc5 100644
--- a/packages/Keyguard/res/values-gl-rES/strings.xml
+++ b/packages/Keyguard/res/values-gl-rES/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"A tarxeta SIM está bloqueada."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"A tarxeta SIM está bloqueada mediante un PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarxeta SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo mediante padrón"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo mediante PIN"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo mediante contrasinal"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zona do padrón"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zona para pasar o dedo"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN da tarxeta SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK da tarxeta SIM"</string>
diff --git a/packages/Keyguard/res/values-gu-rIN/strings.xml b/packages/Keyguard/res/values-gu-rIN/strings.xml
index eddd1a1..d288b3f 100644
--- a/packages/Keyguard/res/values-gu-rIN/strings.xml
+++ b/packages/Keyguard/res/values-gu-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM કાર્ડ લૉક કરેલ છે."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM કાર્ડ, PUK-લૉક કરેલ છે."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM કાર્ડ અનલૉક કરી રહ્યાં છે…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"પેટર્ન અનલૉક."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"પિન અનલૉક."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"પાસવર્ડ અનલૉક કરો."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"પેટર્ન ક્ષેત્ર."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"સ્લાઇડ ક્ષેત્ર."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ક્ષેત્ર"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ક્ષેત્ર"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ક્ષેત્ર"</string>
diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml
index 8069c5e..bf36312 100644
--- a/packages/Keyguard/res/values-hi/strings.xml
+++ b/packages/Keyguard/res/values-hi/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"सिम कार्ड लॉक है."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"सिम कार्ड PUK द्वारा लॉक किया हुआ है."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"सिम कार्ड अनलॉक हो रहा है…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"आकार अनलॉक."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलॉक."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"आकार क्षेत्र."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"सिम पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"सिम पिइउके क्षेत्र"</string>
diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml
index 044786d..169bc57 100644
--- a/packages/Keyguard/res/values-hr/strings.xml
+++ b/packages/Keyguard/res/values-hr/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica zaključana je PUK-om."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Uzorak za otključavanje."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje PIN-om."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje zaporkom."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Područje uzorka."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Područje klizanja."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Područje PIN-a"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Područje PIN-a za SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Područje PUK-a za SIM"</string>
diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml
index e54a89f..bc3bf4e 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"A SIM kártya le van zárva."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"A SIM kártya le van zárva a PUK kóddal."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM kártya feloldása..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Feloldás mintával"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Feloldás PIN kóddal"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Feloldás jelszóval"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mintaterület"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Csúsztatási terület"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-kód területe"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN-kód területe"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK kód területe"</string>
diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml
index 6758a2e..4aacf8f 100644
--- a/packages/Keyguard/res/values-hy-rAM/strings.xml
+++ b/packages/Keyguard/res/values-hy-rAM/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM քարտը կողպված է:"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM քարտը PUK-ով կողպված է:"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM քարտը ապակողպվում է..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Սխեմայով ապակողպում:"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin-ն ապակողպված է:"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Գաղտնաբառի ապակողպում:"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Սխեմայի տարածք:"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Սահեցման տարածք:"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN կոդի տարածք"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM քարտի PIN կոդի տարածք"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM քարտի PUK կոդի տարածք"</string>
diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml
index 6f8e7f1..dda63a8 100644
--- a/packages/Keyguard/res/values-in/strings.xml
+++ b/packages/Keyguard/res/values-in/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kartu SIM terkunci."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kartu SIM terkunci PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Membuka kartu SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci dengan pola."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci dengan PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci dengan sandi."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area pola."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area geser."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Bidang PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Bidang PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Bidang PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-is-rIS/strings.xml b/packages/Keyguard/res/values-is-rIS/strings.xml
index 279ffcf..278e031 100644
--- a/packages/Keyguard/res/values-is-rIS/strings.xml
+++ b/packages/Keyguard/res/values-is-rIS/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortið er læst."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortið er PUK-læst."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Tekur SIM-kort úr lás…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Opnun með mynstri."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Opnun með PIN-númeri."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Opnun með aðgangsorði."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Svæði mynsturs."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Stroksvæði."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-svæði"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-svæði SIM-korts"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-svæði SIM-korts"</string>
diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml
index 728974d..98bcae4 100644
--- a/packages/Keyguard/res/values-it/strings.xml
+++ b/packages/Keyguard/res/values-it/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La SIM è bloccata."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La SIM è bloccata tramite PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Sblocco scheda SIM..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Sblocco con sequenza."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Sblocco con PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Sblocco con password."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area sequenza."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area di scorrimento."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Area PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Area PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Area PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml
index 47d0728..8d1ada3 100644
--- a/packages/Keyguard/res/values-iw/strings.xml
+++ b/packages/Keyguard/res/values-iw/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"‏כרטיס ה-SIM נעול."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"‏כרטיס SIM נעול באמצעות PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"‏מבטל נעילה של כרטיס SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ביטול נעילה באמצעות ציור קו."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"‏ביטול נעילה באמצעות מספר PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ביטול נעילה באמצעות סיסמה."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"אזור ציור קו."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"אזור הסטה."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"‏אזור עבור קוד PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"‏אזור עבור קוד PIN של SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"‏אזור עבור קוד PUK של SIM"</string>
diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml
index d30355f..c4b4c98 100644
--- a/packages/Keyguard/res/values-ja/strings.xml
+++ b/packages/Keyguard/res/values-ja/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIMカードはロックされています。"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIMカードはPUKでロックされています。"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIMカードをロック解除しています…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"パターンロックを解除します。"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PINロックを解除します。"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"パスワードロックを解除します。"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"パターンエリアです。"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"スライドエリアです。"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PINエリア"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PINエリア"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUKエリア"</string>
diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml
index a398e00..658194ff 100644
--- a/packages/Keyguard/res/values-ka-rGE/strings.xml
+++ b/packages/Keyguard/res/values-ka-rGE/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM ბარათი დაბლოკილია."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM ბარათი დაბლოკილია PUK კოდით."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"მიმდინარეობს SIM ბარათის განბლოკვა…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"განბლოკვა ნიმუშით."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"განბლოკვა Pin-ით."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"პაროლის განბლოკვა"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ნიმუშების სივრცე."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"გადასრიალების სივრცე."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-ის არე"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-ის PIN-ის არე"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-ის PUK-ის არე"</string>
diff --git a/packages/Keyguard/res/values-kk-rKZ/strings.xml b/packages/Keyguard/res/values-kk-rKZ/strings.xml
index be261fb..2eb3948 100644
--- a/packages/Keyguard/res/values-kk-rKZ/strings.xml
+++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картасы бекітулі."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картасының PUK коды бекітілген."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картасының бекітпесін ашуда…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Кескін арқылы ашу."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin арқылы ашу."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Құпия сөз арқылы ашу."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Кескін арқылы ашу аймағы."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Сырғыту аймағы."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN аумағы"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN аумағы"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK аумағы"</string>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index 4d3f6e8..fce46c7 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ស៊ីម​កាត​​ជាប់​សោ។"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ស៊ីម​កាត​ជាប់​កូដ​​ PUK ។"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"កំពុង​ដោះ​សោ​ស៊ីម​កាត..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"លំនាំ​ដោះ​សោ​។"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"កូដ PIN ដោះ​សោ។"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ពាក្យ​សម្ងាត់​ដោះ​សោ​។"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ផ្ទៃ​លំនាំ។"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ផ្ទៃ​រុញ។"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ប្រអប់លេខសម្ងាត់"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ប្រអប់លេខសម្ងាត់ស៊ីម"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ប្រអប់ PUK ស៊ីម"</string>
diff --git a/packages/Keyguard/res/values-kn-rIN/strings.xml b/packages/Keyguard/res/values-kn-rIN/strings.xml
index 5691a63..7bac9c6 100644
--- a/packages/Keyguard/res/values-kn-rIN/strings.xml
+++ b/packages/Keyguard/res/values-kn-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ಸಿಮ್‌ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ಸಿಮ್‌ ಕಾರ್ಡ್ ಅನ್ನು PUK-ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ಸಿಮ್‌ ಕಾರ್ಡ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ಪ್ಯಾಟರ್ನ್ ಅನ್‌ಲಾಕ್."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ಪಿನ್ ಅನ್‌ಲಾಕ್."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ಪಾಸ್‌ವರ್ಡ್ ಅನ್‌ಲಾಕ್."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ಪ್ಯಾಟರ್ನ್ ಪ್ರದೇಶ."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ಸ್ಲೈಡ್ ಪ್ರದೇಶ."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ಪಿನ್ ಪ್ರದೇಶ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ಸಿಮ್ ಪಿನ್ ಪ್ರದೇಶ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ಸಿಮ್ PUK ಪ್ರದೇಶ"</string>
diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml
index 2eeef2b..5d40d4d 100644
--- a/packages/Keyguard/res/values-ko/strings.xml
+++ b/packages/Keyguard/res/values-ko/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 카드가 잠겨 있습니다."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 카드가 PUK 잠김 상태입니다."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM 카드 잠금해제 중..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"패턴을 사용하여 잠금해제합니다."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"핀을 사용하여 잠금해제합니다."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"비밀번호를 사용하여 잠금해제합니다."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"패턴을 그리는 부분입니다."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"슬라이드하는 부분입니다."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 영역"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN 영역"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK 영역"</string>
diff --git a/packages/Keyguard/res/values-ky-rKG/strings.xml b/packages/Keyguard/res/values-ky-rKG/strings.xml
index d42b1fa..a485528 100644
--- a/packages/Keyguard/res/values-ky-rKG/strings.xml
+++ b/packages/Keyguard/res/values-ky-rKG/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта бөгөттөлгөн."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карта PUK-бөгөттө."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-карта бөгөттөн чыгарылууда…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Үлгү менен ачуу."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Пин код менен ачуу."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Сырсөз менен ачуу."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Үлгү аймагы."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Жылмыштыруу аймагы."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN аймагы"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN аймагы"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK аймагы"</string>
diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml
index 8e7c813..29a1b56 100644
--- a/packages/Keyguard/res/values-lo-rLA/strings.xml
+++ b/packages/Keyguard/res/values-lo-rLA/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ຊິມກາດຖືກລັອກ."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ຊິມກາດຖືກລັອກດ້ວຍລະຫັດ PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ກຳລັງປົດລັອກຊິມກາດ..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ປົດລັອກດ້ວຍຮູບແບບ."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ປົດລັອກດ້ວຍ PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ການປົດລັອກດ້ວຍລະຫັດຜ່ານ."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ພື້ນທີ່ຮູບແບບ."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ເລື່ອນພື້ນທີ່."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ພື້ນ​ທີ່ PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ພື້ນ​ທີ່ PIN ຂອງ SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ພື້ນ​ທີ່ PUK ຂອງ SIM"</string>
diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml
index 653c089..fd41efc 100644
--- a/packages/Keyguard/res/values-lt/strings.xml
+++ b/packages/Keyguard/res/values-lt/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kortelė užrakinta."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kortelė užrakinta PUK kodu."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Atrakinama SIM kortelė…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Atrakinimas pagal piešinį."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Atrakinimas įvedus PIN kodą."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Atrakinimas įvedus slaptažodį."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Atrakinimo pagal piešinį sritis."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slydimo sritis."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN kodo sritis"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM kortelės PIN kodo sritis"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM kortelės PUK kodo sritis"</string>
diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml
index 449659e..f801d64 100644
--- a/packages/Keyguard/res/values-lv/strings.xml
+++ b/packages/Keyguard/res/values-lv/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karte ir bloķēta."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karte ir bloķēta ar PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Notiek SIM kartes atbloķēšana..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Autorizācija ar kombināciju."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Autorizācija ar PIN kodu."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Autorizācija ar paroli."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kombinācijas ievades apgabals."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Apgabals, kur vilkt ar pirkstu."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN apgabals"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN apgabals"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK apgabals"</string>
diff --git a/packages/Keyguard/res/values-mk-rMK/strings.xml b/packages/Keyguard/res/values-mk-rMK/strings.xml
index a6ee921..9d833f0 100644
--- a/packages/Keyguard/res/values-mk-rMK/strings.xml
+++ b/packages/Keyguard/res/values-mk-rMK/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"СИМ картичката е заклучена."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"СИМ картичката е заклучена со ПУК."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"СИМ картичката се отклучува..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Отклучување со шема."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Отклучување со пин."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Отклучување со лозинка."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област за шема."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област за лизгање."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Поле за PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Поле за PIN на СИМ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Поле за ПУК на СИМ"</string>
diff --git a/packages/Keyguard/res/values-ml-rIN/strings.xml b/packages/Keyguard/res/values-ml-rIN/strings.xml
index fa39ae1..5d93cf0 100644
--- a/packages/Keyguard/res/values-ml-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ml-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"സിം കാർഡ് ലോക്കുചെയ്‌തു."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"സിം കാർഡ് PUK-ലോക്ക് ചെയ്‌തതാണ്."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"സിം കാർഡ് അൺലോക്കുചെയ്യുന്നു…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"പാറ്റേൺ അൺലോക്ക്."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"പിൻ അൺലോക്ക്."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"പാസ്‌വേഡ് അൺലോക്ക്."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"പാറ്റേൺ ഏരിയ."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"സ്ലൈഡ് ഏരിയ."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ഏരിയ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ഏരിയ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ഏരിയ"</string>
diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml
index fae0328..8641e31 100644
--- a/packages/Keyguard/res/values-mn-rMN/strings.xml
+++ b/packages/Keyguard/res/values-mn-rMN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM карт түгжигдсэн."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картны PUK-түгжигдсэн."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картны түгжээг гаргаж байна…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Тайлах хээ."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Тайлах пин."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Тайлах нууц үг."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Хээний хэсэг."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Гулсуулах хэсэг."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN талбар"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN талбар"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK талбар"</string>
diff --git a/packages/Keyguard/res/values-mr-rIN/strings.xml b/packages/Keyguard/res/values-mr-rIN/strings.xml
index 57a95be..8bcaad6 100644
--- a/packages/Keyguard/res/values-mr-rIN/strings.xml
+++ b/packages/Keyguard/res/values-mr-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"सिम कार्ड लॉक झाले आहे."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"सिम कार्ड PUK-लॉक केलेले आहे."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"सिम कार्ड अनलॉक करत आहे…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"नमुना अनलॉक."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"संकेतशब्द अनलॉक."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"नमुना क्षेत्र."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"सिम पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"सिम PUK क्षेत्र"</string>
diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml
index 803d40a..b7b093f 100644
--- a/packages/Keyguard/res/values-ms-rMY/strings.xml
+++ b/packages/Keyguard/res/values-ms-rMY/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kad SIM dikunci."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kad SIM dikunci dengan PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Membuka kunci kad SIM..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci corak."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci pin."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci kata laluan."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kawasan corak."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kawasan luncur."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Kawasan PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Kawasan PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Kawasan PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-my-rMM/strings.xml b/packages/Keyguard/res/values-my-rMM/strings.xml
index fd800e4..7a7664e 100644
--- a/packages/Keyguard/res/values-my-rMM/strings.xml
+++ b/packages/Keyguard/res/values-my-rMM/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ဆင်းမ်ကဒ် သော့ကျနေပါသည်"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ဆင်းမ်ကဒ် ရဲ့ ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် သော့ကျနေပါသည်"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ဆင်းမ်ကဒ် ကို သော့ဖွင့်နေပါသည်"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ပုံစံဖြင့် သော့ဖွင့်ခြင်း"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ပင်နံပါတ်ဖြင့် သော့ဖွင့်ခြင်း"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"စကားဝှက်ဖြင့် သော့ဖွင့်ခြင်း"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ပုံစံနေရာ"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ဘေးတိုက်ပွတ်ဆွဲရန် နေရာ"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN နေရာ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN နေရာ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK နေရာ"</string>
diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml
index 1bdf444..e0035da 100644
--- a/packages/Keyguard/res/values-nb/strings.xml
+++ b/packages/Keyguard/res/values-nb/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet er låst."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortet er PUK-låst."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Låser opp SIM-kortet ..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mønsteropplåsning."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-opplåsning."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Passordopplåsning."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Dra-felt."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-området"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-området for SIM-kortet"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-området for SIM-kortet"</string>
diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml
index 2cf863d..47f5432 100644
--- a/packages/Keyguard/res/values-ne-rNP/strings.xml
+++ b/packages/Keyguard/res/values-ne-rNP/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM कार्ड लक गरियो।"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM कार्ड PUK-लक छ।"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM कार्ड अनलक हुँदै…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ढाँचा अनलक।"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin अनलक"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलक।"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ढाँचा क्षेत्र।"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र।"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पीन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM पुक क्षेत्र"</string>
diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml
index a33165d..c44381e 100644
--- a/packages/Keyguard/res/values-nl/strings.xml
+++ b/packages/Keyguard/res/values-nl/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Simkaart is vergrendeld."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Simkaart is vergrendeld met PUK-code."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Simkaart ontgrendelen…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ontgrendeling via patroon."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ontgrendeling via pincode."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ontgrendeling via wachtwoord."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Tekengebied voor patroon."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Schuifgebied."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Gebied voor pincode"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Gebied voor sim-pincode"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Gebied voor sim-pukcode"</string>
diff --git a/packages/Keyguard/res/values-pa-rIN/strings.xml b/packages/Keyguard/res/values-pa-rIN/strings.xml
index 8cf86a0..16ca29c 100644
--- a/packages/Keyguard/res/values-pa-rIN/strings.xml
+++ b/packages/Keyguard/res/values-pa-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM ਕਾਰਡ PUK-ਲੌਕਡ ਹੈ।"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM ਕਾਰਡ ਅਨਲੌਕ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ਪੈਟਰਨ ਅਨਲੌਕ।"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin ਅਨਲੌਕ।"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ਪਾਸਵਰਡ ਅਨਲੌਕ।"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ਪੈਟਰਨ ਖੇਤਰ।"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ਖੇਤਰ ਸਲਾਈਡ ਕਰੋ।"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ਖੇਤਰ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ਖੇਤਰ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ਖੇਤਰ"</string>
diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml
index ee20850..f0980da 100644
--- a/packages/Keyguard/res/values-pl/strings.xml
+++ b/packages/Keyguard/res/values-pl/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Karta SIM jest zablokowana."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Karta SIM jest zablokowana za pomocą kodu PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odblokowuję kartę SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odblokowanie wzorem."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odblokowanie kodem PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odblokowanie hasłem."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Obszar wzoru."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Obszar przesuwania."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Miejsce na PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Miejsce na PIN do karty SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Miejsce na PUK do karty SIM"</string>
diff --git a/packages/Keyguard/res/values-pt-rBR/strings.xml b/packages/Keyguard/res/values-pt-rBR/strings.xml
index d7215c1..2663337 100644
--- a/packages/Keyguard/res/values-pt-rBR/strings.xml
+++ b/packages/Keyguard/res/values-pt-rBR/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado pelo PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando o cartão SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml
index f0b2bbc..e417e07 100644
--- a/packages/Keyguard/res/values-pt-rPT/strings.xml
+++ b/packages/Keyguard/res/values-pt-rPT/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado por PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"A desbloquear o cartão SIM..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio através de sequência."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio através de PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio através de palavra-passe."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área da sequência."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN do SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK do SIM"</string>
diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml
index d7215c1..2663337 100644
--- a/packages/Keyguard/res/values-pt/strings.xml
+++ b/packages/Keyguard/res/values-pt/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado pelo PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando o cartão SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index b1b142e..09a066a 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Cardul SIM este blocat."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Cardul SIM este blocat cu codul PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Se deblochează cardul SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Deblocare cu model."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Deblocare cu PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Deblocare cu parolă."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zonă model."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zonă glisare."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona codului PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona codului PIN al cardului SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona codului PUK al cardului SIM"</string>
diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml
index 264e42c..7466c66 100644
--- a/packages/Keyguard/res/values-ru/strings.xml
+++ b/packages/Keyguard/res/values-ru/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта заблокирована"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Для разблокировки SIM-карты требуется PUK-код."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Разблокировка SIM-карты…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Графический ключ"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ввода графического ключа"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область слайдера"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-код"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-код SIM-карты"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-код SIM-карты"</string>
diff --git a/packages/Keyguard/res/values-si-rLK/strings.xml b/packages/Keyguard/res/values-si-rLK/strings.xml
index 607e8ac..5f96e8c 100644
--- a/packages/Keyguard/res/values-si-rLK/strings.xml
+++ b/packages/Keyguard/res/values-si-rLK/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM පත අගුළු දමා ඇත."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM පත PUK අගුළු ලා ඇත."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM පත අගුළු හරිමින්..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"රටා අගුළු ඇරීම."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN අගුළු ඇරීම."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"මුරපද අගුළු ඇරීම."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"රටා ප්‍රදේශය."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"සර්පණ ප්‍රදේශය."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN කොටස"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN කොටස"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK කොටස"</string>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index 4cbfd51..82a4f1d4 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta je uzamknutá."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta je uzamknutá pomocou kódu PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Prebieha odomykanie SIM karty..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odomknutie vzorom."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odomknutie kódom PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odomknutie heslom."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblasť na zadanie bezpečnostného vzoru."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblasť na prejdenie prstom."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblasť kódu PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblasť kódu PIN SIM karty"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblasť kódu PUK SIM karty"</string>
diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml
index 91083f5..9100bd3 100644
--- a/packages/Keyguard/res/values-sl/strings.xml
+++ b/packages/Keyguard/res/values-sl/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kartica SIM je zaklenjena."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kartica SIM je zaklenjena s kodo PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odklepanje kartice SIM …"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odklepanje z vzorcem."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odklepanje s kodo PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odklepanje z geslom."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Območje vzorca."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Območje podrsanja."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Območje za kodo PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Območje za kodo PIN za SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Območje za kodo PUK za SIM"</string>
diff --git a/packages/Keyguard/res/values-sq-rAL/strings.xml b/packages/Keyguard/res/values-sq-rAL/strings.xml
index 7f4becb..31d31b7 100644
--- a/packages/Keyguard/res/values-sq-rAL/strings.xml
+++ b/packages/Keyguard/res/values-sq-rAL/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Karta SIM është e kyçur."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Karta SIM është e kyçur me PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Po shkyç kartën SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Shkyçje me motiv."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Shkyçje me PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Shkyçja e fjalëkalimit."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zona e motivit."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zonën e rrëshqitjes."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona PIN e kartës SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona e PUK-ut të kartës SIM"</string>
diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml
index 62614a6..840cae7 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картица је закључана."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картица је закључана PUK кодом."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Откључавање SIM картице…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Откључавање шаблоном."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Откључавање PIN-ом."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Откључавање лозинком."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област шаблона."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област превлачења."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Област за PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Област за PIN за SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Област за PUK за SIM"</string>
diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml
index 378f047..527c8e6 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet är låst."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortet är PUK-låst."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Låser upp SIM-kort …"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås upp med grafiskt lösenord."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås upp med PIN-kod."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås upp med lösenord."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Fält för grafiskt lösenord."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Fält med dragreglage."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Pinkodsområde"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Pinkodsområde för SIM-kort"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-kodsområde för SIM-kort"</string>
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index b570e9f..c2e7ac9 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kadi imefungwa."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kadi imefungwa na PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Inafungua SIM kadi..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Kufungua kwa ruwaza."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Kufungua kwa PIN."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Kufungua kwa nenosiri."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Eneo la ruwaza."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Eneo la slaidi."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Eneo la PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Eneo la PIN ya SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Eneo la PUK ya SIM"</string>
diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml
index 2e3f588..c80ddce 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"சிம் கார்டு PUK ஆல் பூட்டப்பட்டது."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"வடிவம் மூலம் திறத்தல்."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin மூலம் திறத்தல்."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"கடவுச்சொல் மூலம் திறத்தல்."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"வடிவப் பகுதி."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ஸ்லைடு பகுதி."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN பகுதி"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"சிம் PIN பகுதி"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"சிம் PUK பகுதி"</string>
diff --git a/packages/Keyguard/res/values-te-rIN/strings.xml b/packages/Keyguard/res/values-te-rIN/strings.xml
index 6c521aa..a72a85b 100644
--- a/packages/Keyguard/res/values-te-rIN/strings.xml
+++ b/packages/Keyguard/res/values-te-rIN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"సిమ్ కార్డు లాక్ చేయబడింది."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"సిమ్ కార్డు PUK లాక్ చేయబడింది."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"సిమ్ కార్డును అన్‌లాక్ చేస్తోంది…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"నమూనా అన్‌లాక్."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"పిన్ అన్‌లాక్."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"పాస్‌వర్డ్ అన్‌లాక్."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"నమూనా ప్రాంతం."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"స్లయిడ్ ప్రాంతం."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ప్రాంతం"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ప్రాంతం"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ప్రాంతం"</string>
diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml
index 1799fe8..e094d35 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ซิมการ์ดถูกล็อก"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ซิมการ์ดถูกล็อกด้วย PUK"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"กำลังปลดล็อกซิมการ์ด…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"การปลดล็อกด้วยรูปแบบ"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"การปลดล็อกด้วย PIN"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"การปลดล็อกด้วยรหัสผ่าน"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"พื้นที่สำหรับรูปแบบ"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"พื้นที่สำหรับการเลื่อน"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"พื้นที่ PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"พื้นที่ PIN ของซิม"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"พื้นที่ PUK ของซิม"</string>
diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml
index 39cad72..73492e2 100644
--- a/packages/Keyguard/res/values-tl/strings.xml
+++ b/packages/Keyguard/res/values-tl/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Naka-lock ang SIM card."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Naka-lock ang SIM card gamit ang PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ina-unlock ang SIM card…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pag-unlock ng pattern."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pag-unlock ng pin."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Pag-unlock ng password."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bahagi ng pattern."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bahagi ng slide."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Lugar ng PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Lugar ng PIN ng SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Lugar ng PUK ng SIM"</string>
diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml
index ffcbd12..3ef0705 100644
--- a/packages/Keyguard/res/values-tr/strings.xml
+++ b/packages/Keyguard/res/values-tr/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kart kilitli."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kart PUK kilidi devrede."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM kart kilidi açılıyor…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desenle kilit açma."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin koduyla kilit açma."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Şifreyle kilit açma."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Desen alanı."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kaydırma alanı."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN alanı"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN alanı"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK alanı"</string>
diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml
index be19281..a508689 100644
--- a/packages/Keyguard/res/values-uk/strings.xml
+++ b/packages/Keyguard/res/values-uk/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карту заблоковано."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карту заблоковано PUK-кодом."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Розблокування SIM-карти…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Розблокування ключем."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Розблокування PIN-кодом."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Розблокування паролем."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ключа."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область повзунка."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-код"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-код SIM-карти"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-код SIM-карти"</string>
diff --git a/packages/Keyguard/res/values-ur-rPK/strings.xml b/packages/Keyguard/res/values-ur-rPK/strings.xml
index 63f4e85..1070d58 100644
--- a/packages/Keyguard/res/values-ur-rPK/strings.xml
+++ b/packages/Keyguard/res/values-ur-rPK/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"‏SIM کارڈ مقفل ہے۔"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"‏SIM کارڈ PUK-مقفل ہے۔"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"‏SIM کارڈ غیر مقفل کیا جا رہا ہے…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"پیٹرن کے ذریعے غیر مقفل کریں۔"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"پن کے ذریعے غیر مقفل کریں۔"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"پاس ورڈ کے ذریعہ غیر مقفل کریں۔"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"پیٹرن کا علاقہ۔"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"سلائیڈ کرنے کا علاقہ۔"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"‏PIN کا علاقہ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"‏SIM PIN کا علاقہ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"‏SIM PUK کا علاقہ"</string>
diff --git a/packages/Keyguard/res/values-uz-rUZ/strings.xml b/packages/Keyguard/res/values-uz-rUZ/strings.xml
index ad71a56..a9df331 100644
--- a/packages/Keyguard/res/values-uz-rUZ/strings.xml
+++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta qulflangan."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta PUK kod bilan qulflangan."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM karta qulfi ochilmoqda…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Grafik kalit bilan ochish."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin qulfini ochish."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parolli qulfni ochish."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Grafik kalit chiziladigan hudud."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Maydonni silang"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-kod maydoni"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM karta PIN kodi maydoni"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM karta PUK kodi maydoni"</string>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index ad3da9f..c6d2bd8 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Thẻ SIM đã bị khóa."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Thẻ SIM đã bị khóa PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Đang mở khóa thẻ SIM…"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mở khóa bằng hình."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Mở khóa bằng mã pin."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Mở khóa bằng mật khẩu."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Khu vực hình."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Khu vực trượt."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Khu vực mã PIN"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Khu vực mã PIN của SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Khu vực PUK của SIM"</string>
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index 274d9e6..0723ab1 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM卡已被锁定。"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM卡已被PUK码锁定。"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解锁SIM卡..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"图案解锁。"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN码解锁。"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密码解锁。"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"图案区域。"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑动区域。"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 码区域"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM 卡 PIN 码区域"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM 卡 PUK 码区域"</string>
diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml
index 7d51154..5b1903b 100644
--- a/packages/Keyguard/res/values-zh-rHK/strings.xml
+++ b/packages/Keyguard/res/values-zh-rHK/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 卡處於鎖定狀態。"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 卡處於 PUK 鎖定狀態。"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解開上鎖的 SIM 卡..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"圖案解鎖。"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密碼解鎖。"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"圖案區域。"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑動區域。"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 區域"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN 區域"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK 區域"</string>
diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml
index 50895f3..388f8e1 100644
--- a/packages/Keyguard/res/values-zh-rTW/strings.xml
+++ b/packages/Keyguard/res/values-zh-rTW/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 卡處於鎖定狀態。"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 卡處於 PUK 鎖定狀態"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解除 SIM 卡鎖定..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"圖案解鎖。"</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密碼解鎖。"</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"圖案區域。"</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑動區域。"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 區"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM 卡 PIN 區"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM 卡 PUK 區"</string>
diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml
index c5f2a85..a9b6263 100644
--- a/packages/Keyguard/res/values-zu/strings.xml
+++ b/packages/Keyguard/res/values-zu/strings.xml
@@ -46,11 +46,6 @@
     <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Ikhadi le-SIM likhiyiwe."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Ikhadi le-SIM likhiywe nge-PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ivula ikhadi le-SIM..."</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ukuvula ngephethini."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ukuvula ngephinikhodi."</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ukuvula ngephasiwedi."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Indawo yephethini."</string>
-    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Indawo yokushelelisa."</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Indawo yephinikhodi"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Indawo yephinikhodi ye-SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Indawo ye-SIM PUK"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index b75f529..ddccc14 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -42,16 +42,21 @@
  * Displays an alphanumeric (latin-1) key entry for the user to enter
  * an unlock password
  */
-
 public class KeyguardPasswordView extends KeyguardAbsKeyInputView
         implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
 
     private final boolean mShowImeAtScreenOn;
     private final int mDisappearYTranslation;
 
+    // A delay constant to be used in a workaround for the situation where InputMethodManagerService
+    // is not switched to the new user yet.
+    // TODO: Remove this by ensuring such a race condition never happens.
+    private static final int DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON = 500;  // 500ms
+
     InputMethodManager mImm;
     private TextView mPasswordEntry;
     private TextViewInputDisabler mPasswordEntryDisabler;
+    private View mSwitchImeButton;
 
     private Interpolator mLinearOutSlowInInterpolator;
     private Interpolator mFastOutLinearInInterpolator;
@@ -141,12 +146,31 @@
         mPasswordEntry.requestFocus();
     }
 
+    private void updateSwitchImeButton() {
+        // If there's more than one IME, enable the IME switcher button
+        final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE;
+        final boolean shouldBeVisible = hasMultipleEnabledIMEsOrSubtypes(mImm, false);
+        if (wasVisible != shouldBeVisible) {
+            mSwitchImeButton.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE);
+        }
+
+        // TODO: Check if we still need this hack.
+        // If no icon is visible, reset the start margin on the password field so the text is
+        // still centered.
+        if (mSwitchImeButton.getVisibility() != View.VISIBLE) {
+            android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
+            if (params instanceof MarginLayoutParams) {
+                final MarginLayoutParams mlp = (MarginLayoutParams) params;
+                mlp.setMarginStart(0);
+                mPasswordEntry.setLayoutParams(params);
+            }
+        }
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        boolean imeOrDeleteButtonVisible = false;
-
         mImm = (InputMethodManager) getContext().getSystemService(
                 Context.INPUT_METHOD_SERVICE);
 
@@ -171,31 +195,29 @@
 
         mPasswordEntry.requestFocus();
 
-        // If there's more than one IME, enable the IME switcher button
-        View switchImeButton = findViewById(R.id.switch_ime_button);
-        if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) {
-            switchImeButton.setVisibility(View.VISIBLE);
-            imeOrDeleteButtonVisible = true;
-            switchImeButton.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    mCallback.userActivity(); // Leave the screen on a bit longer
-                    // Do not show auxiliary subtypes in password lock screen.
-                    mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
-                }
-            });
-        }
-
-        // If no icon is visible, reset the start margin on the password field so the text is
-        // still centered.
-        if (!imeOrDeleteButtonVisible) {
-            android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
-            if (params instanceof MarginLayoutParams) {
-                final MarginLayoutParams mlp = (MarginLayoutParams) params;
-                mlp.setMarginStart(0);
-                mPasswordEntry.setLayoutParams(params);
+        mSwitchImeButton = findViewById(R.id.switch_ime_button);
+        mSwitchImeButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mCallback.userActivity(); // Leave the screen on a bit longer
+                // Do not show auxiliary subtypes in password lock screen.
+                mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
             }
-        }
+        });
+
+        // If there's more than one IME, enable the IME switcher button
+        updateSwitchImeButton();
+
+        // When we the current user is switching, InputMethodManagerService sometimes has not
+        // switched internal state yet here. As a quick workaround, we check the keyboard state
+        // again.
+        // TODO: Remove this workaround by ensuring such a race condition never happens.
+        postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                updateSwitchImeButton();
+            }
+        }, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
index aa74940..8290842 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
@@ -49,11 +49,6 @@
     int PROMPT_REASON_AFTER_LOCKOUT = 5;
 
     /**
-     * Some auth is required because a single wrong credential has been tried.
-     */
-    int PROMPT_REASON_WRONG_CREDENTIAL = 6;
-
-    /**
      * Interface back to keyguard to tell it when security
      * @param callback
      */
diff --git a/packages/SettingsLib/res/values-ky-rKG/arrays.xml b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
index a06ecfb..1aadb9b 100644
--- a/packages/SettingsLib/res/values-ky-rKG/arrays.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
@@ -147,7 +147,7 @@
   <string-array name="track_frame_time_entries">
     <item msgid="2193584639058893150">"Өчүк"</item>
     <item msgid="2751513398307949636">"Экранда тилке катары"</item>
-    <item msgid="2355151170975410323">"Төмөнкүдө <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
+    <item msgid="2355151170975410323">"Төмөнкүдө: <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
   </string-array>
   <string-array name="debug_hw_overdraw_entries">
     <item msgid="8190572633763871652">"Өчүк"</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 3838143..3bdb6fb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -863,4 +863,7 @@
     <!-- Label for Help and feedback menu item -->
     <string name="help_feedback_label">Help &amp; feedback</string>
 
+    <!-- Content description for drawer menu button [CHAR_LIMIT=30]-->
+    <string name="content_description_menu_button">Menu</string>
+
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index cf08f50..687b3fc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -167,7 +167,7 @@
         return (policy != null) ? policy.warningBytes : WARNING_DISABLED;
     }
 
-    public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
+    private void setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes) {
         final NetworkPolicy policy = getOrCreatePolicy(template);
         policy.warningBytes = warningBytes;
         policy.inferred = false;
@@ -175,12 +175,28 @@
         writeAsync();
     }
 
+    public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
+        long limitBytes = getPolicyLimitBytes(template);
+
+        // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes
+        warningBytes = Math.min(warningBytes, limitBytes);
+        setPolicyWarningBytesInner(template, warningBytes);
+    }
+
     public long getPolicyLimitBytes(NetworkTemplate template) {
         final NetworkPolicy policy = getPolicy(template);
         return (policy != null) ? policy.limitBytes : LIMIT_DISABLED;
     }
 
+
     public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
+        long warningBytes = getPolicyWarningBytes(template);
+
+        // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes
+        if (warningBytes > limitBytes) {
+            setPolicyWarningBytesInner(template, limitBytes);
+        }
+
         final NetworkPolicy policy = getOrCreatePolicy(template);
         policy.limitBytes = limitBytes;
         policy.inferred = false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 6658c14..a50b366 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -226,6 +226,7 @@
     public void showMenuIcon() {
         mShowingMenu = true;
         getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
+        getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button);
         getActionBar().setDisplayHomeAsUpEnabled(true);
     }
 
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index f0c19dc..a1cf3ea 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -40,5 +40,5 @@
     <string name="bugreport_info_title" msgid="2306030793918239804">"Tajuk pepijat"</string>
     <string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan pepijat"</string>
     <string name="save" msgid="4781509040564835759">"Simpan"</string>
-    <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Kongsi Laporan pepijat?"</string>
+    <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Kongsi Laporan pepijat"</string>
 </resources>
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
index 1e0eaac..872eb7a 100644
--- a/packages/Shell/tests/Android.mk
+++ b/packages/Shell/tests/Android.mk
@@ -8,7 +8,9 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    ub-uiautomator \
 
 LOCAL_PACKAGE_NAME := ShellTests
 LOCAL_INSTRUMENTATION_FOR := Shell
diff --git a/packages/Shell/tests/AndroidManifest.xml b/packages/Shell/tests/AndroidManifest.xml
index 54b0802..6d564c6 100644
--- a/packages/Shell/tests/AndroidManifest.xml
+++ b/packages/Shell/tests/AndroidManifest.xml
@@ -36,7 +36,7 @@
         </activity>
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.shell"
         android:label="Tests for Shell" />
 
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 902c71d..dde71eb 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -36,6 +36,13 @@
 import static com.android.shell.BugreportProgressService.POLLING_FREQUENCY;
 import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
@@ -56,6 +63,13 @@
 
 import libcore.io.Streams;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningServiceInfo;
 import android.app.Instrumentation;
@@ -68,11 +82,12 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.Log;
@@ -96,7 +111,8 @@
  * <strong>NOTE</strong>: these tests only work if the device is unlocked.
  */
 @LargeTest
-public class BugreportReceiverTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BugreportReceiverTest {
     private static final String TAG = "BugreportReceiverTest";
 
     // Timeout for UI operations, in milliseconds.
@@ -149,9 +165,10 @@
     private UiBot mUiBot;
     private CustomActionSendMultipleListener mListener;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Rule public TestName mName = new TestName();
+
+    @Before
+    public void setUp() throws Exception {
         Log.i(TAG, getName() + ".setup()");
         Instrumentation instrumentation = getInstrumentation();
         mContext = instrumentation.getTargetContext();
@@ -181,13 +198,13 @@
         mUiBot.turnScreenOn();
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         Log.i(TAG, getName() + ".tearDown()");
         cancelExistingNotifications();
-        super.tearDown();
     }
 
+    @Test
     public void testProgress() throws Exception {
         resetProperties();
         sendBugreportStarted(1000);
@@ -233,6 +250,7 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testProgress_cancel() throws Exception {
         resetProperties();
         sendBugreportStarted(1000);
@@ -249,6 +267,7 @@
         waitForService(false);
     }
 
+    @Test
     public void testProgress_takeExtraScreenshot() throws Exception {
         resetProperties();
         sendBugreportStarted(1000);
@@ -267,6 +286,7 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testScreenshotFinishesAfterBugreport() throws Exception {
         resetProperties();
 
@@ -286,6 +306,7 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testProgress_changeDetailsInvalidInput() throws Exception {
         resetProperties();
         sendBugreportStarted(1000);
@@ -331,6 +352,7 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testProgress_cancelBugClosesDetailsDialog() throws Exception {
         resetProperties();
         sendBugreportStarted(1000);
@@ -346,10 +368,12 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testProgress_changeDetailsPlainBugreport() throws Exception {
         changeDetailsTest(true);
     }
 
+    @Test
     public void testProgress_changeDetailsZippedBugreport() throws Exception {
         changeDetailsTest(false);
     }
@@ -383,10 +407,12 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
         changeJustDetailsTest(true);
     }
 
+    @Test
     public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
         changeJustDetailsTest(false);
     }
@@ -410,6 +436,7 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception {
         resetProperties();
         sendBugreportStarted(ID, PID, NAME, 1000);
@@ -453,6 +480,7 @@
      * Tests the scenario where the initial screenshot and dumpstate are finished while the user
      * is changing the info in the details screen.
      */
+    @Test
     public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
         bugreportFinishedWhileChangingDetailsTest(false);
     }
@@ -461,6 +489,7 @@
      * Tests the scenario where dumpstate is finished while the user is changing the info in the
      * details screen, but the initial screenshot finishes afterwards.
      */
+    @Test
     public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
         bugreportFinishedWhileChangingDetailsTest(true);
     }
@@ -500,14 +529,17 @@
         assertServiceNotRunning();
     }
 
+    @Test
     public void testBugreportFinished_withWarningFirstTime() throws Exception {
         bugreportFinishedWithWarningTest(null);
     }
 
+    @Test
     public void testBugreportFinished_withWarningUnknownState() throws Exception {
         bugreportFinishedWithWarningTest(STATE_UNKNOWN);
     }
 
+    @Test
     public void testBugreportFinished_withWarningShowAgain() throws Exception {
         bugreportFinishedWithWarningTest(STATE_SHOW);
     }
@@ -560,6 +592,7 @@
         assertEquals("Didn't change state", STATE_HIDE, newState);
     }
 
+    @Test
     public void testShareBugreportAfterServiceDies() throws Exception {
         sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
         waitForService(false);
@@ -567,21 +600,25 @@
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
     }
 
+    @Test
     public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
     }
 
+    @Test
     public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
     }
 
+    @Test
     public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
     }
 
+    @Test
     public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
@@ -1001,6 +1038,14 @@
         mUiBot.assertNotVisibleById("android:id/alertTitle");
     }
 
+    private String getName() {
+        return mName.getMethodName();
+    }
+
+    private Instrumentation getInstrumentation() {
+        return InstrumentationRegistry.getInstrumentation();
+    }
+
     private static void sleep(long ms) {
         Log.d(TAG, "sleeping for " + ms + "ms");
         SystemClock.sleep(ms);
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index 0a2f320..49119fb 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -41,5 +41,6 @@
         android:layout_height="wrap_content"
         android:layout_marginStart="-50dp"
         android:src="@drawable/ic_pause_white_24dp"
-        android:text="@string/pip_pause" />
+        android:text="@string/pip_pause"
+        android:visibility="gone" />
 </merge>
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index ea26bba..775b157 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -18,7 +18,8 @@
     android:id="@+id/volume_zen_footer"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical" > <!-- extends LinearLayout -->
+    android:orientation="vertical"
+    android:paddingBottom="8dp" > <!-- extends LinearLayout -->
 
     <View
         android:id="@+id/zen_embedded_divider"
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4893598..fe27459 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -602,7 +602,7 @@
     <string name="keycode_description" msgid="1403795192716828949">"Näppäinkoodi-painikkeet sallivat näppäimistön näppäimien lisäämisen navigointipalkkiin. Kun painiketta painetaan, se jäljittelee valittua näppäintä. Valitse ensin painikkeen kohteena oleva näppäin, sitten painikkeessa näkyvä kuva."</string>
     <string name="select_keycode" msgid="7413765103381924584">"Valitse näppäimistön näppäin"</string>
     <string name="preview" msgid="9077832302472282938">"Esikatselu"</string>
-    <string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä."</string>
+    <string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Poista vetämällä tähän."</string>
     <string name="qs_edit" msgid="2232596095725105230">"Muokkaa"</string>
     <string name="tuner_time" msgid="6572217313285536011">"Aika"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5acc177..a93c3e2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -313,7 +313,7 @@
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
     <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Données mobiles"</string>
-    <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Consommation des données"</string>
+    <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Conso des données"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
     <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite dépassée"</string>
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilisés"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index de96cb0..a15ba26 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -309,7 +309,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
-    <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn nháy"</string>
+    <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn pin"</string>
     <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dữ liệu di động"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Sử dụng dữ liệu"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dữ liệu còn lại"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8b592c2..c4ef80f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -86,7 +86,6 @@
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
 
@@ -626,10 +625,7 @@
                 return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
             } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
-            } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL) != 0) {
-                return KeyguardSecurityView.PROMPT_REASON_WRONG_CREDENTIAL;
             }
-
             return KeyguardSecurityView.PROMPT_REASON_NONE;
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index ac90ce7..19a5d52 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -237,6 +237,10 @@
         mQSPanel.setListening(mListening && mQsExpanded);
     }
 
+    public void setHeaderListening(boolean listening) {
+        mHeader.setListening(listening);
+    }
+
     public void setQsExpansion(float expansion, float headerTranslation) {
         if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
         mQsExpansion = expansion;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b6597a0..ed0fc1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -251,10 +251,12 @@
         if (mListening) {
             refreshAllTiles();
         }
-        if (listening) {
-            mBrightnessController.registerCallbacks();
-        } else {
-            mBrightnessController.unregisterCallbacks();
+        if (mBrightnessView.getVisibility() == View.VISIBLE) {
+            if (listening) {
+                mBrightnessController.registerCallbacks();
+            } else {
+                mBrightnessController.unregisterCallbacks();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 4638c85..1343c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -26,6 +26,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Rect;
+import android.graphics.Xfermode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableWrapper;
@@ -224,6 +225,12 @@
         }
 
         @Override
+        public void setXfermode(@Nullable Xfermode mode) {
+            // DrawableWrapper does not call this for us.
+            getDrawable().setXfermode(mode);
+        }
+
+        @Override
         public int getIntrinsicWidth() {
             return -1;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f27f8f5..812c5c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1617,6 +1617,9 @@
         if (mQsExpanded) {
             onQsExpansionStarted();
         }
+        // Since there are QS tiles in the header now, we need to make sure we start listening
+        // immediately so they can be up to date.
+        mQsContainer.setHeaderListening(true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index c9cde9d..047085d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -501,7 +501,7 @@
         mMotion.startDismiss(new Runnable() {
             @Override
             public void run() {
-                updateExpandedH(false);
+                updateExpandedH(false /* expanding */, true /* dismissing */);
             }
         });
         if (mAccessibilityMgr.isEnabled()) {
@@ -547,45 +547,47 @@
         mHandler.sendEmptyMessageDelayed(H.UPDATE_BOTTOM_MARGIN, getConservativeCollapseDuration());
     }
 
-    private void updateExpandedH(final boolean expanded) {
+    private void updateExpandedH(final boolean expanded, final boolean dismissing) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
         mExpandButtonAnimationRunning = isAttached();
         if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded);
         updateExpandButtonH();
         updateFooterH();
-        final VolumeRow activeRow = getActiveRow();
-        mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
-        AutoTransition transition = new AutoTransition();
-        transition.setDuration(mExpandButtonAnimationDuration);
-        transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-        transition.addListener(new Transition.TransitionListener() {
-            @Override
-            public void onTransitionStart(Transition transition) {
-            }
-
-            @Override
-            public void onTransitionEnd(Transition transition) {
-                mWindow.setLayout(
-                        mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
-            }
-
-            @Override
-            public void onTransitionCancel(Transition transition) {
-                mWindow.setLayout(
-                        mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
-            }
-
-            @Override
-            public void onTransitionPause(Transition transition) {
-            }
-
-            @Override
-            public void onTransitionResume(Transition transition) {
-            }
-        });
         TransitionManager.endTransitions(mDialogView);
-        TransitionManager.beginDelayedTransition(mDialogView, transition);
+        final VolumeRow activeRow = getActiveRow();
+        if (!dismissing) {
+            mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
+            AutoTransition transition = new AutoTransition();
+            transition.setDuration(mExpandButtonAnimationDuration);
+            transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+            transition.addListener(new Transition.TransitionListener() {
+                @Override
+                public void onTransitionStart(Transition transition) {
+                }
+
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    mWindow.setLayout(
+                            mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
+                }
+
+                @Override
+                public void onTransitionCancel(Transition transition) {
+                }
+
+                @Override
+                public void onTransitionPause(Transition transition) {
+                    mWindow.setLayout(
+                            mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
+                }
+
+                @Override
+                public void onTransitionResume(Transition transition) {
+                }
+            });
+            TransitionManager.beginDelayedTransition(mDialogView, transition);
+        }
         updateRowsH(activeRow);
         rescheduleTimeoutH();
     }
@@ -1035,7 +1037,7 @@
             if (mExpandButtonAnimationRunning) return;
             final boolean newExpand = !mExpanded;
             Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
-            updateExpandedH(newExpand);
+            updateExpandedH(newExpand, false /* dismissing */);
         }
     };
 
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 82b3050..242eca8 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -34,6 +34,8 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import libcore.io.IoUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 
 import java.io.File;
@@ -112,56 +114,58 @@
             touch.close();
             fullBackupFile(empty, data);
 
-            // only back up the wallpaper if we've been told it's allowed
-            if (mWm.isWallpaperBackupEligible()) {
-                if (DEBUG) {
-                    Slog.v(TAG, "Wallpaper is backup-eligible");
-                }
+            SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+            final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
+            final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1);
 
-                SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
-                final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
-                final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1);
+            final int sysGeneration =
+                    mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM);
+            final int lockGeneration =
+                    mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM);
+            final boolean sysChanged = (sysGeneration != lastSysGeneration);
+            final boolean lockChanged = (lockGeneration != lastLockGeneration);
 
-                final int sysGeneration =
-                        mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM);
-                final int lockGeneration =
-                        mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM);
-                final boolean sysChanged = (sysGeneration != lastSysGeneration);
-                final boolean lockChanged = (lockGeneration != lastLockGeneration);
+            final boolean sysEligible = mWm.isWallpaperBackupEligible(FLAG_SYSTEM);
+            final boolean lockEligible = mWm.isWallpaperBackupEligible(FLAG_LOCK);
 
-                if (DEBUG) {
-                    Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged);
-                    Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
-                }
-                if (mWallpaperInfo.exists()) {
-                    if (sysChanged || lockChanged || !infoStage.exists()) {
-                        if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
-                        FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
-                    }
-                    fullBackupFile(infoStage, data);
-                }
-                if (mWallpaperFile.exists()) {
-                    if (sysChanged || !imageStage.exists()) {
-                        if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
-                        FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
-                    }
-                    fullBackupFile(imageStage, data);
-                    prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
-                }
+                // There might be a latent lock wallpaper file present but unused: don't
+                // include it in the backup if that's the case.
+                ParcelFileDescriptor lockFd = mWm.getWallpaperFile(FLAG_LOCK, UserHandle.USER_SYSTEM);
+                final boolean hasLockWallpaper = (lockFd != null);
+                IoUtils.closeQuietly(lockFd);
 
-                // Don't try to store the lock image if we overran our quota last time
-                if (mLockWallpaperFile.exists() && !mQuotaExceeded) {
-                    if (lockChanged || !lockImageStage.exists()) {
-                        if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
-                        FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
-                    }
-                    fullBackupFile(lockImageStage, data);
-                    prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
+            if (DEBUG) {
+                Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged);
+                Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
+                Slog.v(TAG, "sysEligble=" + sysEligible);
+                Slog.v(TAG, "lockEligible=" + lockEligible);
+            }
+
+            // only back up the wallpapers if we've been told they're eligible
+            if ((sysEligible || lockEligible) && mWallpaperInfo.exists()) {
+                if (sysChanged || lockChanged || !infoStage.exists()) {
+                    if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
+                    FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
                 }
-            } else {
-                if (DEBUG) {
-                    Slog.v(TAG, "Wallpaper not backup-eligible; writing no data");
+                fullBackupFile(infoStage, data);
+            }
+            if (sysEligible && mWallpaperFile.exists()) {
+                if (sysChanged || !imageStage.exists()) {
+                    if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
+                    FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
                 }
+                fullBackupFile(imageStage, data);
+                prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
+            }
+
+            // Don't try to store the lock image if we overran our quota last time
+            if (lockEligible && hasLockWallpaper && mLockWallpaperFile.exists() && !mQuotaExceeded) {
+                if (lockChanged || !lockImageStage.exists()) {
+                    if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
+                    FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
+                }
+                fullBackupFile(lockImageStage, data);
+                prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
             }
         } catch (Exception e) {
             Slog.e(TAG, "Unable to back up wallpaper", e);
@@ -199,15 +203,20 @@
         final File imageStage = new File (filesDir, IMAGE_STAGE);
         final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
 
+        // If we restored separate lock imagery, the system wallpaper should be
+        // applied as system-only; but if there's no separate lock image, make
+        // sure to apply the restored system wallpaper as both.
+        final int sysWhich = FLAG_SYSTEM | (lockImageStage.exists() ? 0 : FLAG_LOCK);
+
         try {
             // First off, revert to the factory state
-            mWm.clear(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
+            mWm.clear(FLAG_SYSTEM | FLAG_LOCK);
 
             // It is valid for the imagery to be absent; it means that we were not permitted
             // to back up the original image on the source device, or there was no user-supplied
             // wallpaper image present.
-            restoreFromStage(imageStage, infoStage, "wp", WallpaperManager.FLAG_SYSTEM);
-            restoreFromStage(lockImageStage, infoStage, "kwp", WallpaperManager.FLAG_LOCK);
+            restoreFromStage(imageStage, infoStage, "wp", sysWhich);
+            restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK);
         } catch (Exception e) {
             Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
         } finally {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 983a656..ea25f74 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -21,6 +21,7 @@
 import android.Manifest;
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.GestureDescription;
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.annotation.NonNull;
@@ -2787,7 +2788,7 @@
         }
 
         @Override
-        public void sendMotionEvents(int sequence, ParceledListSlice events) {
+        public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
             synchronized (mLock) {
                 if (mSecurityPolicy.canPerformGestures(this)) {
                     final long endMillis =
@@ -2801,9 +2802,16 @@
                         }
                     }
                     if (mMotionEventInjector != null) {
-                        mMotionEventInjector.injectEvents((List<MotionEvent>) events.getList(),
-                                mServiceInterface, sequence);
-                        return;
+                        List<GestureDescription.GestureStep> steps = gestureSteps.getList();
+                        List<MotionEvent> events = GestureDescription.MotionEventGenerator
+                                .getMotionEventsFromGestureSteps(steps);
+                        // Confirm that the motion events end with an UP event.
+                        if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) {
+                            mMotionEventInjector.injectEvents(events, mServiceInterface, sequence);
+                            return;
+                        } else {
+                            Slog.e(LOG_TAG, "Gesture is not well-formed");
+                        }
                     } else {
                         Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
                     }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index 915d839..9cc53f0 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -34,6 +34,7 @@
 
     @Override
     public void onStart() {
+        mImpl.onStart();
         publishBinderService(Context.APPWIDGET_SERVICE, mImpl);
         AppWidgetBackupBridge.register(mImpl);
     }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 47094be..5ec3f2b 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -201,21 +201,21 @@
 
     private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>();
 
-    private final BackupRestoreController mBackupRestoreController;
+    private BackupRestoreController mBackupRestoreController;
 
     private final Context mContext;
 
-    private final IPackageManager mPackageManager;
-    private final AlarmManager mAlarmManager;
-    private final UserManager mUserManager;
-    private final AppOpsManager mAppOpsManager;
-    private final KeyguardManager mKeyguardManager;
-    private final DevicePolicyManagerInternal mDevicePolicyManagerInternal;
+    private IPackageManager mPackageManager;
+    private AlarmManager mAlarmManager;
+    private UserManager mUserManager;
+    private AppOpsManager mAppOpsManager;
+    private KeyguardManager mKeyguardManager;
+    private DevicePolicyManagerInternal mDevicePolicyManagerInternal;
 
-    private final SecurityPolicy mSecurityPolicy;
+    private SecurityPolicy mSecurityPolicy;
 
-    private final Handler mSaveStateHandler;
-    private final Handler mCallbackHandler;
+    private Handler mSaveStateHandler;
+    private Handler mCallbackHandler;
 
     private Locale mLocale;
 
@@ -224,10 +224,13 @@
     private boolean mSafeMode;
     private int mMaxWidgetBitmapMemory;
 
-    private final IconUtilities mIconUtilities;
+    private IconUtilities mIconUtilities;
 
     AppWidgetServiceImpl(Context context) {
         mContext = context;
+    }
+
+    public void onStart() {
         mPackageManager = AppGlobals.getPackageManager();
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -238,7 +241,7 @@
         mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
         mBackupRestoreController = new BackupRestoreController();
         mSecurityPolicy = new SecurityPolicy();
-        mIconUtilities = new IconUtilities(context);
+        mIconUtilities = new IconUtilities(mContext);
 
         computeMaximumWidgetBitmapMemory();
         registerBroadcastReceiver();
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 0316093..20cca16 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2699,7 +2699,7 @@
         public void scheduleDateChangedEvent() {
             Calendar calendar = Calendar.getInstance();
             calendar.setTimeInMillis(System.currentTimeMillis());
-            calendar.set(Calendar.HOUR, 0);
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
             calendar.set(Calendar.MINUTE, 0);
             calendar.set(Calendar.SECOND, 0);
             calendar.set(Calendar.MILLISECOND, 0);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 488f0e7..6b73fec 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -49,7 +49,6 @@
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.IDeviceIdleController;
 import android.os.IMaintenanceActivityListener;
 import android.os.Looper;
@@ -1238,7 +1237,7 @@
         }
     }
 
-    public final class LocalService {
+    public class LocalService {
         public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
                 String reason) {
             addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 2de09a3..801a436 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -52,6 +52,7 @@
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
 import android.os.ServiceManager;
+import android.os.StrictMode;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -1367,6 +1368,10 @@
             return VerifyCredentialResponse.ERROR;
         }
 
+        // We're potentially going to be doing a bunch of disk I/O below as part
+        // of unlocking the user, so yell if calling from the main thread.
+        StrictMode.noteDiskRead();
+
         if (storedHash.version == CredentialHash.VERSION_LEGACY) {
             byte[] hash = credentialUtil.toHash(credential, userId);
             if (Arrays.equals(hash, storedHash.hash)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0ffc35b..09a3a17 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2341,7 +2341,7 @@
                                                 Process.SCHED_OTHER, 0);
                                         }
                                     } catch (IllegalArgumentException e) {
-                                        Slog.e(TAG, "Failed to set scheduling policy, thread does"
+                                        Slog.w(TAG, "Failed to set scheduling policy, thread does"
                                                 + " not exist:\n" + e);
                                     }
                                 }
@@ -3807,6 +3807,15 @@
             app.killedByAm = false;
             checkTime(startTime, "startProcess: starting to update pids map");
             synchronized (mPidsSelfLocked) {
+                ProcessRecord oldApp;
+                // If there is already an app occupying that pid that hasn't been cleaned up
+                if ((oldApp = mPidsSelfLocked.get(startResult.pid)) != null && !app.isolated) {
+                    // Clean up anything relating to this pid first
+                    Slog.w(TAG, "Reusing pid " + startResult.pid
+                            + " while app is still mapped to it");
+                    cleanUpApplicationRecordLocked(oldApp, false, false, -1,
+                            true /*replacingPid*/);
+                }
                 this.mPidsSelfLocked.put(startResult.pid, app);
                 if (isActivityProcess) {
                     Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
@@ -5039,7 +5048,8 @@
     private final void handleAppDiedLocked(ProcessRecord app,
             boolean restarting, boolean allowRestart) {
         int pid = app.pid;
-        boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
+        boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
+                false /*replacingPid*/);
         if (!kept && !restarting) {
             removeLruProcessLocked(app);
             if (pid > 0) {
@@ -12572,10 +12582,15 @@
                     proc.vrThreadTid = tid;
 
                     // promote to FIFO now if the tid is non-zero
-                    if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP
-                            && proc.vrThreadTid > 0) {
-                        Process.setThreadScheduler(proc.vrThreadTid,
+                    try {
+                        if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
+                            proc.vrThreadTid > 0) {
+                            Process.setThreadScheduler(proc.vrThreadTid,
                                 Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                        }
+                    } catch (IllegalArgumentException e) {
+                        Slog.e(TAG, "Failed to set scheduling policy, thread does"
+                               + " not exist:\n" + e);
                     }
                 }
             }
@@ -16811,7 +16826,8 @@
      * app that was passed in must remain on the process lists.
      */
     private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
-            boolean restarting, boolean allowRestart, int index) {
+            boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
+        Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid);
         if (index >= 0) {
             removeLruProcessLocked(app);
             ProcessList.remove(app.pid);
@@ -16942,7 +16958,9 @@
         if (!app.persistent || app.isolated) {
             if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                     "Removing non-persistent process during cleanup: " + app);
-            removeProcessNameLocked(app.processName, app.uid);
+            if (!replacingPid) {
+                removeProcessNameLocked(app.processName, app.uid);
+            }
             if (mHeavyWeightProcess == app) {
                 mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
                         mHeavyWeightProcess.userId, 0));
@@ -20350,17 +20368,29 @@
                         if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
                             // Switch VR thread for app to SCHED_FIFO
                             if (mInVrMode && app.vrThreadTid != 0) {
-                                Process.setThreadScheduler(app.vrThreadTid,
-                                    Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                try {
+                                    Process.setThreadScheduler(app.vrThreadTid,
+                                        Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                } catch (IllegalArgumentException e) {
+                                    // thread died, ignore
+                                }
                             }
                             if (mUseFifoUiScheduling) {
                                 // Switch UI pipeline for app to SCHED_FIFO
                                 app.savedPriority = Process.getThreadPriority(app.pid);
-                                Process.setThreadScheduler(app.pid,
-                                    Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
-                                if (app.renderThreadTid != 0) {
-                                    Process.setThreadScheduler(app.renderThreadTid,
+                                try {
+                                    Process.setThreadScheduler(app.pid,
                                         Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                } catch (IllegalArgumentException e) {
+                                    // thread died, ignore
+                                }
+                                if (app.renderThreadTid != 0) {
+                                    try {
+                                        Process.setThreadScheduler(app.renderThreadTid,
+                                            Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                    } catch (IllegalArgumentException e) {
+                                        // thread died, ignore
+                                    }
                                     if (DEBUG_OOM_ADJ) {
                                         Slog.d("UI_FIFO", "Set RenderThread (TID " +
                                             app.renderThreadTid + ") to FIFO");
@@ -20374,7 +20404,11 @@
                                 // Boost priority for top app UI and render threads
                                 Process.setThreadPriority(app.pid, -10);
                                 if (app.renderThreadTid != 0) {
-                                    Process.setThreadPriority(app.renderThreadTid, -10);
+                                    try {
+                                        Process.setThreadPriority(app.renderThreadTid, -10);
+                                    } catch (IllegalArgumentException e) {
+                                        // thread died, ignore
+                                    }
                                 }
                             }
                         }
@@ -21258,7 +21292,7 @@
                             // Ignore exceptions.
                         }
                     }
-                    cleanUpApplicationRecordLocked(app, false, true, -1);
+                    cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
                     mRemovedProcesses.remove(i);
 
                     if (app.persistent) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index d02fbbf..219e095 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -304,6 +304,11 @@
         boolean didSomething = false;
         final BroadcastRecord br = mPendingBroadcast;
         if (br != null && br.curApp.pid == app.pid) {
+            if (br.curApp != app) {
+                Slog.e(TAG, "App mismatch when sending pending broadcast to "
+                        + app.processName + ", intended target is " + br.curApp.processName);
+                return false;
+            }
             try {
                 mPendingBroadcast = null;
                 processCurBroadcastLocked(br, app);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 64dea57..7587847 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -746,9 +746,8 @@
                                     BluetoothProfile.A2DP);
         }
 
-        mHdmiManager =
-                (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE);
-        if (mHdmiManager != null) {
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
+            mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
             synchronized (mHdmiManager) {
                 mHdmiTvClient = mHdmiManager.getTvClient();
                 if (mHdmiTvClient != null) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 61af8ed..d6cc9fc 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -102,9 +102,6 @@
     // Trigger proximity if distance is less than 5 cm.
     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
 
-    // Brightness animation ramp rate in brightness units per second.
-    private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
-
     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
@@ -243,8 +240,9 @@
     private boolean mAppliedDimming;
     private boolean mAppliedLowPower;
 
-    // Brightness ramp rate fast.
+    // Brightness animation ramp rates in brightness units per second
     private final int mBrightnessRampRateFast;
+    private final int mBrightnessRampRateSlow;
 
     // The controller for the automatic brightness level.
     private AutomaticBrightnessController mAutomaticBrightnessController;
@@ -307,6 +305,8 @@
 
         mBrightnessRampRateFast = resources.getInteger(
                 com.android.internal.R.integer.config_brightness_ramp_rate_fast);
+        mBrightnessRampRateSlow = resources.getInteger(
+                com.android.internal.R.integer.config_brightness_ramp_rate_slow);
 
         int lightSensorRate = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
@@ -703,7 +703,7 @@
         if (!mPendingScreenOff) {
             if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
                 animateScreenBrightness(brightness,
-                        slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);
+                        slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
             } else {
                 animateScreenBrightness(brightness, 0);
             }
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index d9af7cb..07fa2ce 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TypeEvaluator;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
@@ -361,13 +362,12 @@
             if (setActivated) {
                 mController.setActivated(activated);
             }
-            updateNextAlarm();
+            updateNextAlarm(mIsActivated, now);
         }
 
-        private void updateNextAlarm() {
-            if (mIsActivated != null) {
-                final Calendar now = Calendar.getInstance();
-                final Calendar next = mIsActivated ? mEndTime.getDateTimeAfter(now)
+        private void updateNextAlarm(@Nullable Boolean activated, @NonNull Calendar now) {
+            if (activated != null) {
+                final Calendar next = activated ? mEndTime.getDateTimeAfter(now)
                         : mStartTime.getDateTimeAfter(now);
                 mAlarmManager.setExact(AlarmManager.RTC, next.getTimeInMillis(), TAG, this, null);
             }
@@ -396,10 +396,11 @@
 
         @Override
         public void onActivated(boolean activated) {
+            final Calendar now = Calendar.getInstance();
             if (mIsActivated != null) {
-                mLastActivatedTime = Calendar.getInstance();
+                mLastActivatedTime = now;
             }
-            updateNextAlarm();
+            updateNextAlarm(activated, now);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d8e5f63..9ca609f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -133,7 +133,6 @@
 import android.os.HandlerThread;
 import android.os.IDeviceIdleController;
 import android.os.INetworkManagementService;
-import android.os.IPowerManager;
 import android.os.Message;
 import android.os.MessageQueue.IdleHandler;
 import android.os.PowerManager;
@@ -287,7 +286,6 @@
     private static final int MSG_LIMIT_REACHED = 5;
     private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
     private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
-    private static final int MSG_SCREEN_ON_CHANGED = 8;
     private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
     private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
     private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
@@ -295,7 +293,6 @@
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
-    private final IPowerManager mPowerManager;
     private final INetworkStatsService mNetworkStats;
     private final INetworkManagementService mNetworkManager;
     private UsageStatsManagerInternal mUsageStats;
@@ -313,7 +310,6 @@
 
     @GuardedBy("allLocks") volatile boolean mSystemReady;
 
-    @GuardedBy("mUidRulesFirstLock") volatile boolean mScreenOn;
     @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
     @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower;
     @GuardedBy("mUidRulesFirstLock") volatile boolean mDeviceIdleMode;
@@ -419,9 +415,8 @@
     // TODO: migrate notifications to SystemUI
 
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
-            IPowerManager powerManager, INetworkStatsService networkStats,
-            INetworkManagementService networkManagement) {
-        this(context, activityManager, powerManager, networkStats, networkManagement,
+            INetworkStatsService networkStats, INetworkManagementService networkManagement) {
+        this(context, activityManager, networkStats, networkManagement,
                 NtpTrustedTime.getInstance(context), getSystemDir(), false);
     }
 
@@ -430,12 +425,10 @@
     }
 
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
-            IPowerManager powerManager, INetworkStatsService networkStats,
-            INetworkManagementService networkManagement, TrustedTime time, File systemDir,
-            boolean suppressDefaultPolicy) {
+            INetworkStatsService networkStats, INetworkManagementService networkManagement,
+            TrustedTime time, File systemDir, boolean suppressDefaultPolicy) {
         mContext = checkNotNull(context, "missing context");
         mActivityManager = checkNotNull(activityManager, "missing activityManager");
-        mPowerManager = checkNotNull(powerManager, "missing powerManager");
         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
         mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
         mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
@@ -619,8 +612,6 @@
             }
         }
 
-        updateScreenOn();
-
         try {
             mActivityManager.registerUidObserver(mUidObserver,
                     ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE);
@@ -629,14 +620,6 @@
             // ignored; both services live in system_server
         }
 
-        // TODO: traverse existing processes to know foreground state, or have
-        // activitymanager dispatch current state when new observer attached.
-
-        final IntentFilter screenFilter = new IntentFilter();
-        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
-        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
-        mContext.registerReceiver(mScreenReceiver, screenFilter);
-
         // listen for changes to power save whitelist
         final IntentFilter whitelistFilter = new IntentFilter(
                 PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
@@ -735,15 +718,6 @@
         }
     };
 
-    final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // screen-related broadcasts are protected by system, no need
-            // for permissions check.
-            mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
-        }
-    };
-
     final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -1076,6 +1050,8 @@
                 builder.setTicker(title);
                 builder.setContentTitle(title);
                 builder.setContentText(body);
+                builder.setDefaults(Notification.DEFAULT_ALL);
+                builder.setPriority(Notification.PRIORITY_HIGH);
 
                 final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
                 builder.setDeleteIntent(PendingIntent.getBroadcast(
@@ -2524,7 +2500,7 @@
 
     private boolean isUidStateForegroundUL(int state) {
         // only really in foreground when screen is also on
-        return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
+        return state <= ActivityManager.PROCESS_STATE_TOP;
     }
 
     /**
@@ -2595,31 +2571,6 @@
         }
     }
 
-    private void updateScreenOn() {
-        synchronized (mUidRulesFirstLock) {
-            try {
-                mScreenOn = mPowerManager.isInteractive();
-            } catch (RemoteException e) {
-                // ignored; service lives in system_server
-            }
-            updateRulesForScreenUL();
-        }
-    }
-
-    /**
-     * Update rules that might be changed by {@link #mScreenOn} value.
-     */
-    private void updateRulesForScreenUL() {
-        // only update rules for anyone with foreground activities
-        final int size = mUidState.size();
-        for (int i = 0; i < size; i++) {
-            if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
-                final int uid = mUidState.keyAt(i);
-                updateRestrictionRulesForUidUL(uid);
-            }
-        }
-    }
-
     static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
         return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
     }
@@ -3001,12 +2952,8 @@
             mUidRules.put(uid, newUidRules);
         }
 
-        boolean changed = false;
-
         // Second step: apply bw changes based on change of state.
         if (newRule != oldRule) {
-            changed = true;
-
             if ((newRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
                 // Temporarily whitelist foreground app, removing from blacklist if necessary
                 // (since bw_penalty_box prevails over bw_happy_box).
@@ -3086,7 +3033,6 @@
 
         final boolean isIdle = isUidIdle(uid);
         final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
-        final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
         final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
 
@@ -3109,7 +3055,7 @@
         final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
 
         if (LOGV) {
-            Log.v(TAG, "updateRulesForNonMeteredNetworksUL(" + uid + ")"
+            Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
                     + ", isIdle: " + isIdle
                     + ", mRestrictPower: " + mRestrictPower
                     + ", mDeviceIdleMode: " + mDeviceIdleMode
@@ -3351,10 +3297,6 @@
                     }
                     return true;
                 }
-                case MSG_SCREEN_ON_CHANGED: {
-                    updateScreenOn();
-                    return true;
-                }
                 case MSG_UPDATE_INTERFACE_QUOTA: {
                     removeInterfaceQuota((String) msg.obj);
                     // int params need to be stitched back into a long
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4994d6b..ab83c11 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -364,6 +364,7 @@
     private static final boolean DEBUG_TRIAGED_MISSING = false;
     private static final boolean DEBUG_APP_DATA = false;
 
+    /** REMOVE. According to Svet, this was only used to reset permissions during development. */
     static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
 
     private static final boolean DISABLE_EPHEMERAL_APPS = !Build.IS_DEBUGGABLE;
@@ -801,10 +802,9 @@
                     PackageParser.ActivityIntentInfo filter = filters.get(m);
                     domainsSet.addAll(filter.getHostsList());
                 }
-                ArrayList<String> domainsList = new ArrayList<>(domainsSet);
                 synchronized (mPackages) {
                     if (mSettings.createIntentFilterVerificationIfNeededLPw(
-                            packageName, domainsList) != null) {
+                            packageName, domainsSet) != null) {
                         scheduleWriteSettingsLocked();
                     }
                 }
@@ -2873,7 +2873,6 @@
 
         SystemConfig systemConfig = SystemConfig.getInstance();
         ArraySet<String> packages = systemConfig.getLinkedApps();
-        ArraySet<String> domains = new ArraySet<String>();
 
         for (String packageName : packages) {
             PackageParser.Package pkg = mPackages.get(packageName);
@@ -2883,16 +2882,19 @@
                     continue;
                 }
 
-                domains.clear();
+                ArraySet<String> domains = null;
                 for (PackageParser.Activity a : pkg.activities) {
                     for (ActivityIntentInfo filter : a.intents) {
                         if (hasValidDomains(filter)) {
+                            if (domains == null) {
+                                domains = new ArraySet<String>();
+                            }
                             domains.addAll(filter.getHostsList());
                         }
                     }
                 }
 
-                if (domains.size() > 0) {
+                if (domains != null && domains.size() > 0) {
                     if (DEBUG_DOMAIN_VERIFICATION) {
                         Slog.v(TAG, "      + " + packageName);
                     }
@@ -2900,8 +2902,7 @@
                     // state w.r.t. the formal app-linkage "no verification attempted" state;
                     // and then 'always' in the per-user state actually used for intent resolution.
                     final IntentFilterVerificationInfo ivi;
-                    ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName,
-                            new ArrayList<String>(domains));
+                    ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName, domains);
                     ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
                     mSettings.updateIntentFilterVerificationStatusLPw(packageName,
                             INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, userId);
@@ -8164,12 +8165,12 @@
 
             // Just create the setting, don't add it yet. For already existing packages
             // the PkgSetting exists already and doesn't have to be created.
-            pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
-                    destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
+            pkgSetting = mSettings.getPackageWithBenefitsLPw(pkg, origPackage, realName, suid,
+                    destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
                     pkg.applicationInfo.primaryCpuAbi,
                     pkg.applicationInfo.secondaryCpuAbi,
                     pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
-                    user, false);
+                    user);
             if (pkgSetting == null) {
                 throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                         "Creating application package " + pkg.packageName + " failed");
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index e3866df..a4604a6 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -30,15 +30,23 @@
     int appId;
     PackageParser.Package pkg;
     SharedUserSetting sharedUser;
+    /**
+     * Temporary holding space for the shared user ID. While parsing package settings, the
+     * shared users tag may be after the packages. In this case, we must delay linking the
+     * shared user setting with the package setting. The shared user ID lets us link the
+     * two objects.
+     */
+    private int sharedUserId;
 
     PackageSetting(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
             int pVersionCode, int pkgFlags, int privateFlags, String parentPackageName,
-            List<String> childPackageNames) {
+            List<String> childPackageNames, int sharedUserId) {
         super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
                 pVersionCode, pkgFlags, privateFlags, parentPackageName, childPackageNames);
+        this.sharedUserId = sharedUserId;
     }
 
     /**
@@ -47,10 +55,14 @@
      */
     PackageSetting(PackageSetting orig) {
         super(orig);
+        doCopy(orig);
+    }
 
-        appId = orig.appId;
-        pkg = orig.pkg;
-        sharedUser = orig.sharedUser;
+    public int getSharedUserId() {
+        if (sharedUser != null) {
+            return sharedUser.userId;
+        }
+        return sharedUserId;
     }
 
     @Override
@@ -60,6 +72,18 @@
             + " " + name + "/" + appId + "}";
     }
 
+    public void copyFrom(PackageSetting orig) {
+        super.copyFrom(orig);
+        doCopy(orig);
+    }
+
+    private void doCopy(PackageSetting orig) {
+        appId = orig.appId;
+        pkg = orig.pkg;
+        sharedUser = orig.sharedUser;
+        sharedUserId = orig.sharedUserId;
+    }
+
     public PermissionsState getPermissionsState() {
         return (sharedUser != null)
                 ? sharedUser.getPermissionsState()
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 14ca72c..c08bc57 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -147,51 +147,12 @@
                 secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode);
     }
 
-    /**
-     * New instance of PackageSetting with one-level-deep cloning.
-     */
-    @SuppressWarnings("unchecked")
+    /** New instance of PackageSetting with one-level-deep cloning. */
     PackageSettingBase(PackageSettingBase base) {
         super(base);
-
         name = base.name;
         realName = base.realName;
-        codePath = base.codePath;
-        codePathString = base.codePathString;
-        resourcePath = base.resourcePath;
-        resourcePathString = base.resourcePathString;
-        legacyNativeLibraryPathString = base.legacyNativeLibraryPathString;
-        primaryCpuAbiString = base.primaryCpuAbiString;
-        secondaryCpuAbiString = base.secondaryCpuAbiString;
-        cpuAbiOverrideString = base.cpuAbiOverrideString;
-        timeStamp = base.timeStamp;
-        firstInstallTime = base.firstInstallTime;
-        lastUpdateTime = base.lastUpdateTime;
-        versionCode = base.versionCode;
-
-        uidError = base.uidError;
-
-        signatures = new PackageSignatures(base.signatures);
-
-        installPermissionsFixed = base.installPermissionsFixed;
-        userState.clear();
-        for (int i=0; i<base.userState.size(); i++) {
-            userState.put(base.userState.keyAt(i),
-                    new PackageUserState(base.userState.valueAt(i)));
-        }
-        installStatus = base.installStatus;
-
-        origPackage = base.origPackage;
-
-        installerPackageName = base.installerPackageName;
-        isOrphaned = base.isOrphaned;
-        volumeUuid = base.volumeUuid;
-
-        keySetData = new PackageKeySetData(base.keySetData);
-
-        parentPackageName = base.parentPackageName;
-        childPackageNames = (base.childPackageNames != null)
-                ? new ArrayList<>(base.childPackageNames) : null;
+        doCopy(base);
     }
 
     void init(File codePath, File resourcePath, String legacyNativeLibraryPathString,
@@ -237,27 +198,47 @@
     }
 
     /**
-     * Make a shallow copy of this package settings.
+     * Makes a shallow copy of the given package settings.
+     *
+     * NOTE: For some fields [such as keySetData, signatures, userState, verificationInfo, etc...],
+     * the original object is copied and a new one is not created.
      */
-    public void copyFrom(PackageSettingBase base) {
-        mPermissionsState.copyFrom(base.mPermissionsState);
-        primaryCpuAbiString = base.primaryCpuAbiString;
-        secondaryCpuAbiString = base.secondaryCpuAbiString;
-        cpuAbiOverrideString = base.cpuAbiOverrideString;
-        timeStamp = base.timeStamp;
-        firstInstallTime = base.firstInstallTime;
-        lastUpdateTime = base.lastUpdateTime;
-        signatures = base.signatures;
-        installPermissionsFixed = base.installPermissionsFixed;
+    public void copyFrom(PackageSettingBase orig) {
+        super.copyFrom(orig);
+        doCopy(orig);
+    }
+
+    private void doCopy(PackageSettingBase orig) {
+        childPackageNames = (orig.childPackageNames != null)
+                ? new ArrayList<>(orig.childPackageNames) : null;
+        codePath = orig.codePath;
+        codePathString = orig.codePathString;
+        cpuAbiOverrideString = orig.cpuAbiOverrideString;
+        firstInstallTime = orig.firstInstallTime;
+        installPermissionsFixed = orig.installPermissionsFixed;
+        installStatus = orig.installStatus;
+        installerPackageName = orig.installerPackageName;
+        isOrphaned = orig.isOrphaned;
+        keySetData = orig.keySetData;
+        lastUpdateTime = orig.lastUpdateTime;
+        legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
+        // Intentionally skip oldCodePaths; it's not relevant for copies
+        origPackage = orig.origPackage;
+        parentPackageName = orig.parentPackageName;
+        primaryCpuAbiString = orig.primaryCpuAbiString;
+        resourcePath = orig.resourcePath;
+        resourcePathString = orig.resourcePathString;
+        secondaryCpuAbiString = orig.secondaryCpuAbiString;
+        signatures = orig.signatures;
+        timeStamp = orig.timeStamp;
+        uidError = orig.uidError;
         userState.clear();
-        for (int i=0; i<base.userState.size(); i++) {
-            userState.put(base.userState.keyAt(i), base.userState.valueAt(i));
+        for (int i=0; i<orig.userState.size(); i++) {
+            userState.put(orig.userState.keyAt(i), orig.userState.valueAt(i));
         }
-        installStatus = base.installStatus;
-        keySetData = base.keySetData;
-        verificationInfo = base.verificationInfo;
-        installerPackageName = base.installerPackageName;
-        volumeUuid = base.volumeUuid;
+        verificationInfo = orig.verificationInfo;
+        versionCode = orig.versionCode;
+        volumeUuid = orig.volumeUuid;
     }
 
     private PackageUserState modifyUserState(int userId) {
diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
deleted file mode 100644
index da73085..0000000
--- a/services/core/java/com/android/server/pm/PendingPackage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 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.pm;
-
-import java.io.File;
-import java.util.List;
-
-final class PendingPackage extends PackageSettingBase {
-    final int sharedId;
-
-    PendingPackage(String name, String realName, File codePath, File resourcePath,
-            String legacyNativeLibraryPathString, String primaryCpuAbiString,
-            String secondaryCpuAbiString, String cpuAbiOverrideString, int sharedId,
-            int pVersionCode, int pkgFlags, int pkgPrivateFlags, String parentPackageName,
-            List<String> childPackageNames) {
-        super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
-                primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                pVersionCode, pkgFlags, pkgPrivateFlags, parentPackageName, childPackageNames);
-        this.sharedId = sharedId;
-    }
-}
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index a6350fe..8970556 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -19,6 +19,7 @@
 import android.content.pm.PackageParser;
 import android.content.pm.Signature;
 import android.os.Environment;
+import android.os.SystemProperties;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -64,6 +65,8 @@
     // to synchronize access during policy load and access attempts.
     private static List<Policy> sPolicies = new ArrayList<>();
 
+    private static final String PROP_FORCE_RESTORECON = "sys.force_restorecon";
+
     /** Path to version on rootfs */
     private static final File VERSION_FILE = new File("/selinux_version");
 
@@ -322,6 +325,11 @@
      * @return Returns true if the restorecon should occur or false otherwise.
      */
     public static boolean isRestoreconNeeded(File file) {
+        // To investigate boot timing, allow a property to always force restorecon
+        if (SystemProperties.getBoolean(PROP_FORCE_RESTORECON, false)) {
+            return true;
+        }
+
         try {
             final byte[] buf = new byte[20];
             final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SEAPP_HASH, buf);
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 2921032..71e8d51 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -30,10 +30,19 @@
         mPermissionsState = new PermissionsState();
     }
 
-    SettingBase(SettingBase base) {
-        pkgFlags = base.pkgFlags;
-        pkgPrivateFlags = base.pkgPrivateFlags;
-        mPermissionsState = new PermissionsState(base.mPermissionsState);
+    SettingBase(SettingBase orig) {
+        mPermissionsState = new PermissionsState();
+        doCopy(orig);
+    }
+
+    public void copyFrom(SettingBase orig) {
+        doCopy(orig);
+    }
+
+    private void doCopy(SettingBase orig) {
+        pkgFlags = orig.pkgFlags;
+        pkgPrivateFlags = orig.pkgPrivateFlags;
+        mPermissionsState.copyFrom(orig.mPermissionsState);
     }
 
     public PermissionsState getPermissionsState() {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 31a1c36..52313b1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -166,6 +166,7 @@
     private static final boolean DEBUG_STOPPED = false;
     private static final boolean DEBUG_MU = false;
     private static final boolean DEBUG_KERNEL = false;
+    private static final boolean DEBUG_PARSER = false;
 
     private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml";
 
@@ -393,7 +394,7 @@
      * TODO: make this just a local variable that is passed in during package
      * scanning to make it less confusing.
      */
-    private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
+    private final ArrayList<PackageSetting> mPendingPackages = new ArrayList<>();
 
     private final File mSystemDir;
 
@@ -427,18 +428,22 @@
         mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
     }
 
-    PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
+    PackageSetting getPackageLPw(String pkgName) {
+        return peekPackageLPr(pkgName);
+    }
+
+    PackageSetting getPackageWithBenefitsLPw(PackageParser.Package pkg, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
-            int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add)
+            int pkgFlags, int pkgPrivateFlags, UserHandle user)
                     throws PackageManagerException {
         final String name = pkg.packageName;
         final String parentPackageName = (pkg.parentPackage != null)
                 ? pkg.parentPackage.packageName : null;
-        PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
-                resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,
-                pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /*allowInstall*/,
-                parentPackageName, pkg.getChildPackageNames());
+        PackageSetting p = getPackageWithBenefitsLPw(name, origPackage, realName, sharedUser,
+                codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbi,
+                secondaryCpuAbi, pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user,
+                true /*allowInstall*/, parentPackageName, pkg.getChildPackageNames());
         return p;
     }
 
@@ -602,7 +607,7 @@
         p = new PackageSetting(name, realName, codePath, resourcePath,
                 legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
                 cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags, parentPackageName,
-                childPackageNames);
+                childPackageNames, 0 /*userId*/);
         p.appId = uid;
         if (addUserIdLPw(uid, p, name)) {
             mPackages.put(name, p);
@@ -679,11 +684,11 @@
         }
     }
 
-    private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
+    private PackageSetting getPackageWithBenefitsLPw(String name, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags,
-            UserHandle installUser, boolean add, boolean allowInstall, String parentPackage,
+            UserHandle installUser, boolean allowInstall, String parentPackage,
             List<String> childPackageNames) throws PackageManagerException {
         final UserManagerService userManager = UserManagerService.getInstance();
         final PackageSetting disabledPackage = getDisabledSystemPkgLPr(name);
@@ -714,11 +719,6 @@
                 throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                         "Creating application package " + name + " failed");
             }
-            if (add) {
-                // Finish adding new package by adding it and updating shared
-                // user preferences
-                addPackageSettingLPw(p, name, sharedUser);
-            }
         }
         if (peekPackageLPr(name) != null) {
             final List<UserInfo> allUsers = getAllUsers(UserManagerService.getInstance());
@@ -857,7 +857,7 @@
                 pkgSetting = new PackageSetting(originalPkg.name, pkgName, codePath, resourcePath,
                         legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                         null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
-                        parentPkgName, childPkgNames);
+                        parentPkgName, childPkgNames, 0 /*sharedUserId*/);
                 if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
                         + pkgName + " is adopting original package " + originalPkg.name);
                 // Note that we will retain the new package's signature so
@@ -876,7 +876,7 @@
                 pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath,
                         legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                         null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
-                        parentPkgName, childPkgNames);
+                        parentPkgName, childPkgNames, 0 /*sharedUserId*/);
                 pkgSetting.setTimeStamp(codePath.lastModified());
                 pkgSetting.sharedUser = sharedUser;
                 // If this is not a system app, it starts out stopped.
@@ -1025,15 +1025,14 @@
         if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
             p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
         }
-        addPackageSettingLPw(p, pkg.packageName, p.sharedUser);
+        addPackageSettingLPw(p, p.sharedUser);
     }
 
     // Utility method that adds a PackageSetting to mPackages and
     // completes updating the shared user attributes and any restored
     // app link verification state
-    private void addPackageSettingLPw(PackageSetting p, String name,
-            SharedUserSetting sharedUser) {
-        mPackages.put(name, p);
+    private void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
+        mPackages.put(p.name, p);
         if (sharedUser != null) {
             if (p.sharedUser != null && p.sharedUser != sharedUser) {
                 PackageManagerService.reportSettingsProblem(Log.ERROR,
@@ -1067,12 +1066,12 @@
             }
         }
 
-        IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.get(name);
+        IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.get(p.name);
         if (ivi != null) {
             if (DEBUG_DOMAIN_VERIFICATION) {
-                Slog.i(TAG, "Applying restored IVI for " + name + " : " + ivi.getStatusString());
+                Slog.i(TAG, "Applying restored IVI for " + p.name + " : " + ivi.getStatusString());
             }
-            mRestoredIntentFilterVerifications.remove(name);
+            mRestoredIntentFilterVerifications.remove(p.name);
             p.setIntentFilterVerificationInfo(ivi);
         }
     }
@@ -1320,7 +1319,7 @@
 
     /* package protected */
     IntentFilterVerificationInfo createIntentFilterVerificationIfNeededLPw(String packageName,
-            ArrayList<String> domains) {
+            ArraySet<String> domains) {
         PackageSetting ps = mPackages.get(packageName);
         if (ps == null) {
             if (DEBUG_DOMAIN_VERIFICATION) {
@@ -1595,7 +1594,9 @@
             throws XmlPullParserException, IOException {
         IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser);
         packageSetting.setIntentFilterVerificationInfo(ivi);
-        Log.d(TAG, "Read domain verification for package: " + ivi.getPackageName());
+        if (DEBUG_PARSER) {
+            Log.d(TAG, "Read domain verification for package: " + ivi.getPackageName());
+        }
     }
 
     private void readRestoredIntentFilterVerifications(XmlPullParser parser)
@@ -3039,30 +3040,22 @@
         final int N = mPendingPackages.size();
 
         for (int i = 0; i < N; i++) {
-            final PendingPackage pp = mPendingPackages.get(i);
-            Object idObj = getUserIdLPr(pp.sharedId);
-            if (idObj != null && idObj instanceof SharedUserSetting) {
-                try {
-                    PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
-                            (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
-                            pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
-                            pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags,
-                            pp.pkgPrivateFlags, null /*installUser*/, true /*add*/,
-                            false /*allowInstall*/, pp.parentPackageName, pp.childPackageNames);
-                    p.copyFrom(pp);
-                } catch (PackageManagerException e) {
-                    PackageManagerService.reportSettingsProblem(Log.WARN,
-                            "Unable to create application package for " + pp.name);
-                    continue;
-                }
+            final PackageSetting p = mPendingPackages.get(i);
+            final int sharedUserId = p.getSharedUserId();
+            final Object idObj = getUserIdLPr(sharedUserId);
+            if (idObj instanceof SharedUserSetting) {
+                final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
+                p.sharedUser = sharedUser;
+                p.appId = sharedUser.userId;
+                addPackageSettingLPw(p, sharedUser);
             } else if (idObj != null) {
-                String msg = "Bad package setting: package " + pp.name + " has shared uid "
-                        + pp.sharedId + " that is not a shared uid\n";
+                String msg = "Bad package setting: package " + p.name + " has shared uid "
+                        + sharedUserId + " that is not a shared uid\n";
                 mReadMessages.append(msg);
                 PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
             } else {
-                String msg = "Bad package setting: package " + pp.name + " has shared uid "
-                        + pp.sharedId + " that is not defined\n";
+                String msg = "Bad package setting: package " + p.name + " has shared uid "
+                        + sharedUserId + " that is not defined\n";
                 mReadMessages.append(msg);
                 PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
             }
@@ -3535,7 +3528,7 @@
         PackageSetting ps = new PackageSetting(name, realName, codePathFile,
                 new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
                 secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags,
-                parentPackageName, null);
+                parentPackageName, null /*childPackageNames*/, 0 /*sharedUserId*/);
         String timeStampStr = parser.getAttributeValue(null, "ft");
         if (timeStampStr != null) {
             try {
@@ -3627,7 +3620,7 @@
         long timeStamp = 0;
         long firstInstallTime = 0;
         long lastUpdateTime = 0;
-        PackageSettingBase packageSetting = null;
+        PackageSetting packageSetting = null;
         String version = null;
         int versionCode = 0;
         String parentPackageName;
@@ -3746,7 +3739,8 @@
             if (PackageManagerService.DEBUG_SETTINGS)
                 Log.v(PackageManagerService.TAG, "Reading package: " + name + " userId=" + idStr
                         + " sharedUserId=" + sharedIdStr);
-            int userId = idStr != null ? Integer.parseInt(idStr) : 0;
+            final int userId = idStr != null ? Integer.parseInt(idStr) : 0;
+            final int sharedUserId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
             if (resourcePathStr == null) {
                 resourcePathStr = codePathStr;
             }
@@ -3765,7 +3759,7 @@
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                         new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
                         secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
-                        pkgPrivateFlags, parentPackageName, null);
+                        pkgPrivateFlags, parentPackageName, null /*childPackageNames*/);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
                             + userId + " pkg=" + packageSetting);
@@ -3779,20 +3773,19 @@
                     packageSetting.lastUpdateTime = lastUpdateTime;
                 }
             } else if (sharedIdStr != null) {
-                userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
-                if (userId > 0) {
-                    packageSetting = new PendingPackage(name.intern(), realName, new File(
+                if (sharedUserId > 0) {
+                    packageSetting = new PackageSetting(name.intern(), realName, new File(
                             codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
                             primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                            userId, versionCode, pkgFlags, pkgPrivateFlags, parentPackageName,
-                            null);
+                            versionCode, pkgFlags, pkgPrivateFlags, parentPackageName,
+                            null /*childPackageNames*/, sharedUserId);
                     packageSetting.setTimeStamp(timeStamp);
                     packageSetting.firstInstallTime = firstInstallTime;
                     packageSetting.lastUpdateTime = lastUpdateTime;
-                    mPendingPackages.add((PendingPackage) packageSetting);
+                    mPendingPackages.add(packageSetting);
                     if (PackageManagerService.DEBUG_SETTINGS)
                         Log.i(PackageManagerService.TAG, "Reading package " + name
-                                + ": sharedUserId=" + userId + " pkg=" + packageSetting);
+                                + ": sharedUserId=" + sharedUserId + " pkg=" + packageSetting);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Error in package manager settings: package " + name
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index d5767b4..c1fc7f1 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -878,6 +878,9 @@
             saveUserInternalLocked(userId, os, /* forBackup= */ false);
 
             file.finishWrite(os);
+
+            // Remove all dangling bitmap files.
+            cleanupDanglingBitmapDirectoriesLocked(userId);
         } catch (XmlPullParserException | IOException e) {
             Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
             file.failWrite(os);
@@ -929,7 +932,6 @@
         }
         try {
             final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false);
-            cleanupDanglingBitmapDirectoriesLocked(userId, ret);
             return ret;
         } catch (IOException | XmlPullParserException e) {
             Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
@@ -1062,9 +1064,22 @@
         }
     }
 
-    // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L".
+    // Requires mLock held, but "Locked" prefix would look weired so we just say "L".
     protected boolean isUserUnlockedL(@UserIdInt int userId) {
-        return mUnlockedUsers.get(userId);
+        // First, check the local copy.
+        if (mUnlockedUsers.get(userId)) {
+            return true;
+        }
+        // If the local copy says the user is locked, check with AM for the actual state, since
+        // the user might just have been unlocked.
+        // Note we just don't use isUserUnlockingOrUnlocked() here, because it'll return false
+        // when the user is STOPPING, which we still want to consider as "unlocked".
+        final long token = injectClearCallingIdentity();
+        try {
+            return mUserManager.isUserUnlockingOrUnlocked(userId);
+        } finally {
+            injectRestoreCallingIdentity(token);
+        }
     }
 
     // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L".
@@ -1125,14 +1140,8 @@
     // === Caller validation ===
 
     void removeIcon(@UserIdInt int userId, ShortcutInfo shortcut) {
-        if (shortcut.getBitmapPath() != null) {
-            if (DEBUG) {
-                Slog.d(TAG, "Removing " + shortcut.getBitmapPath());
-            }
-            new File(shortcut.getBitmapPath()).delete();
-
-            shortcut.setBitmapPath(null);
-        }
+        // Do not remove the actual bitmap file yet, because if the device crashes before saving
+        // he XML we'd lose the icon.  We just remove all dangling files after saving the XML.
         shortcut.setIconResourceId(0);
         shortcut.setIconResName(null);
         shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES);
@@ -1148,13 +1157,14 @@
         }
     }
 
-    private void cleanupDanglingBitmapDirectoriesLocked(
-            @UserIdInt int userId, @NonNull ShortcutUser user) {
+    private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) {
         if (DEBUG) {
             Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId);
         }
         final long start = injectElapsedRealtime();
 
+        final ShortcutUser user = getUserShortcutsLocked(userId);
+
         final File bitmapDir = getUserBitmapFilePath(userId);
         final File[] children = bitmapDir.listFiles();
         if (children == null) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 772c64e..3df13a9 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -26,11 +26,9 @@
 import android.app.ActivityManagerNative;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.persistentdata.PersistentDataBlockManager;
@@ -188,8 +186,7 @@
         serializer.endTag(null, tag);
     }
 
-    public static void readRestrictions(XmlPullParser parser, Bundle restrictions)
-            throws IOException {
+    public static void readRestrictions(XmlPullParser parser, Bundle restrictions) {
         for (String key : USER_RESTRICTIONS) {
             final String value = parser.getAttributeValue(null, key);
             if (value != null) {
@@ -437,7 +434,13 @@
                     if (newValue) {
                         PersistentDataBlockManager manager = (PersistentDataBlockManager) context
                                 .getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
-                        if (manager != null && manager.getOemUnlockEnabled()) {
+                        if (manager != null
+                                && manager.getOemUnlockEnabled()
+                                && manager.getFlashLockState()
+                                        != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED) {
+                            // Only disable OEM unlock if the bootloader is locked. If it's already
+                            // unlocked, setting the OEM unlock enabled flag to false has no effect
+                            // (the bootloader would remain unlocked).
                             manager.setOemUnlockEnabled(false);
                         }
                     }
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index 6fc15f0..bb91f76 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -103,6 +103,7 @@
     private static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
     private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
     private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
+    private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
 
     private final Context mContext;
     private final WindowManagerFuncs mWindowManagerFuncs;
@@ -298,6 +299,8 @@
                 mItems.add(getVoiceAssistAction());
             } else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
                 mItems.add(getAssistAction());
+            } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
+                mItems.add(new RestartAction());
             } else {
                 Log.e(TAG, "Invalid global action key " + actionKey);
             }
@@ -369,6 +372,38 @@
         }
     }
 
+    private final class RestartAction extends SinglePressAction implements LongPressAction {
+        private RestartAction() {
+            super(R.drawable.ic_restart, R.string.global_action_restart);
+        }
+
+        @Override
+        public boolean onLongPress() {
+            UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+            if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+                mWindowManagerFuncs.rebootSafeMode(true);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public boolean showDuringKeyguard() {
+            return true;
+        }
+
+        @Override
+        public boolean showBeforeProvisioning() {
+            return true;
+        }
+
+        @Override
+        public void onPress() {
+            mWindowManagerFuncs.reboot(false /* confirm */);
+        }
+    }
+
+
     private class BugReportAction extends SinglePressAction implements LongPressAction {
 
         public BugReportAction() {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 60fbabf..9ce147d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -7392,8 +7392,8 @@
     }
 
     private boolean areSystemNavigationKeysEnabled() {
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0) == 1;
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java
index fd63d48..aaac297 100644
--- a/services/core/java/com/android/server/trust/TrustArchive.java
+++ b/services/core/java/com/android/server/trust/TrustArchive.java
@@ -37,6 +37,7 @@
     private static final int TYPE_AGENT_CONNECTED = 4;
     private static final int TYPE_AGENT_STOPPED = 5;
     private static final int TYPE_MANAGING_TRUST = 6;
+    private static final int TYPE_POLICY_CHANGED = 7;
 
     private static final int HISTORY_LIMIT = 200;
 
@@ -99,6 +100,10 @@
         addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, 0, managing));
     }
 
+    public void logDevicePolicyChanged() {
+        addEvent(new Event(TYPE_POLICY_CHANGED, UserHandle.USER_ALL, null, null, 0, 0, false));
+    }
+
     private void addEvent(Event e) {
         if (mEvents.size() >= HISTORY_LIMIT) {
             mEvents.removeFirst();
@@ -112,7 +117,8 @@
         Iterator<Event> iter = mEvents.descendingIterator();
         while (iter.hasNext() && count < limit) {
             Event ev = iter.next();
-            if (userId != UserHandle.USER_ALL && userId != ev.userId) {
+            if (userId != UserHandle.USER_ALL && userId != ev.userId
+                    && ev.userId != UserHandle.USER_ALL) {
                 continue;
             }
 
@@ -122,11 +128,13 @@
             if (userId == UserHandle.USER_ALL) {
                 writer.print("user="); writer.print(ev.userId); writer.print(", ");
             }
-            writer.print("agent=");
-            if (duplicateSimpleNames) {
-                writer.print(ev.agent.flattenToShortString());
-            } else {
-                writer.print(getSimpleName(ev.agent));
+            if (ev.agent != null) {
+                writer.print("agent=");
+                if (duplicateSimpleNames) {
+                    writer.print(ev.agent.flattenToShortString());
+                } else {
+                    writer.print(getSimpleName(ev.agent));
+                }
             }
             switch (ev.type) {
                 case TYPE_GRANT_TRUST:
@@ -181,6 +189,8 @@
                 return "AgentStopped";
             case TYPE_MANAGING_TRUST:
                 return "ManagingTrust";
+            case TYPE_POLICY_CHANGED:
+                return "DevicePolicyChanged";
             default:
                 return "Unknown(" + type + ")";
         }
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index e60488a..216afe6 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -434,12 +434,17 @@
     }
 
     void updateDevicePolicyFeatures() {
+        boolean changed = false;
         for (int i = 0; i < mActiveAgents.size(); i++) {
             AgentInfo info = mActiveAgents.valueAt(i);
             if (info.agent.isConnected()) {
                 info.agent.updateDevicePolicyFeatures();
+                changed = true;
             }
         }
+        if (changed) {
+            mArchive.logDevicePolicyChanged();
+        }
     }
 
     private void removeAgentsOfPackage(String packageName) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 95fbf55..76f2f0e 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1400,9 +1400,7 @@
                     wallpaper.whichPending = which;
                     wallpaper.setComplete = completion;
                     wallpaper.cropHint.set(cropHint);
-                    if ((which & FLAG_SYSTEM) != 0) {
-                        wallpaper.allowBackup = allowBackup;
-                    }
+                    wallpaper.allowBackup = allowBackup;
                 }
                 return pfd;
             } finally {
@@ -1753,12 +1751,14 @@
     }
 
     @Override
-    public boolean isWallpaperBackupEligible(int userId) {
+    public boolean isWallpaperBackupEligible(int which, int userId) {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
             throw new SecurityException("Only the system may call isWallpaperBackupEligible");
         }
 
-        WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
+        WallpaperData wallpaper = (which == FLAG_LOCK)
+                ? mWallpaperMap.get(userId)
+                : mLockWallpaperMap.get(userId);
         return (wallpaper != null) ? wallpaper.allowBackup : false;
     }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index c78e94b..d3dab44 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -517,6 +517,11 @@
                 // placement for this window during this period, one or more frame will
                 // show up with wrong position or scale.
                 win.mWinAnimator.mAnimating = false;
+
+                if (win.mDestroying) {
+                    win.mDestroying = false;
+                    mService.mDestroySurface.remove(win);
+                }
             }
         }
         requestUpdateWallpaperIfNeeded();
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 9d0fb61..d0167bb 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -94,10 +94,7 @@
     float mOriginalX, mOriginalY;
     float mCurrentX, mCurrentY;
     float mThumbOffsetX, mThumbOffsetY;
-    InputChannel mServerChannel, mClientChannel;
-    DragInputEventReceiver mInputEventReceiver;
-    InputApplicationHandle mDragApplicationHandle;
-    InputWindowHandle mDragWindowHandle;
+    InputInterceptor mInputInterceptor;
     WindowState mTargetWindow;
     ArrayList<WindowState> mNotifiedWindows;
     boolean mDragInProgress;
@@ -130,16 +127,13 @@
         mNotifiedWindows = null;
     }
 
-    /**
-     * @param display The Display that the window being dragged is on.
-     */
-    void register(Display display) {
-        if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
-        if (mClientChannel != null) {
-            Slog.e(TAG_WM, "Duplicate register of drag input channel");
-        } else {
-            mDisplayContent = mService.getDisplayContentLocked(display.getDisplayId());
+    class InputInterceptor {
+        InputChannel mServerChannel, mClientChannel;
+        DragInputEventReceiver mInputEventReceiver;
+        InputApplicationHandle mDragApplicationHandle;
+        InputWindowHandle mDragWindowHandle;
 
+        InputInterceptor(Display display) {
             InputChannel[] channels = InputChannel.openInputChannelPair("drag");
             mServerChannel = channels[0];
             mClientChannel = channels[1];
@@ -188,13 +182,8 @@
             }
             mService.pauseRotationLocked();
         }
-    }
 
-    void unregister() {
-        if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel");
-        if (mClientChannel == null) {
-            Slog.e(TAG_WM, "Unregister of nonexistent drag input channel");
-        } else {
+        void tearDown() {
             mService.mInputManager.unregisterInputChannel(mServerChannel);
             mInputEventReceiver.dispose();
             mInputEventReceiver = null;
@@ -214,6 +203,40 @@
         }
     }
 
+    InputChannel getInputChannel() {
+        return mInputInterceptor == null ? null : mInputInterceptor.mServerChannel;
+    }
+
+    InputWindowHandle getInputWindowHandle() {
+        return mInputInterceptor == null ? null : mInputInterceptor.mDragWindowHandle;
+    }
+
+    /**
+     * @param display The Display that the window being dragged is on.
+     */
+    void register(Display display) {
+        if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
+        if (mInputInterceptor != null) {
+            Slog.e(TAG_WM, "Duplicate register of drag input channel");
+        } else {
+            mInputInterceptor = new InputInterceptor(display);
+            mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+        }
+    }
+
+    void unregister() {
+        if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel");
+        if (mInputInterceptor == null) {
+            Slog.e(TAG_WM, "Unregister of nonexistent drag input channel");
+        } else {
+            // Input channel should be disposed on the thread where the input is being handled.
+            mService.mH.obtainMessage(
+                    H.TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor).sendToTarget();
+            mInputInterceptor = null;
+            mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+        }
+    }
+
     int getDragLayerLw() {
         return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
                 * WindowManagerService.TYPE_LAYER_MULTIPLIER
@@ -397,8 +420,6 @@
         // free our resources and drop all the object references
         reset();
         mService.mDragState = null;
-
-        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
     }
 
     void notifyMoveLw(float x, float y) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index b9c55a5..535ce9d 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -249,7 +249,7 @@
             if (DEBUG_DRAG) {
                 Log.d(TAG_WM, "Inserting drag window");
             }
-            final InputWindowHandle dragWindowHandle = mService.mDragState.mDragWindowHandle;
+            final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle();
             if (dragWindowHandle != null) {
                 addInputWindowHandleLw(dragWindowHandle);
             } else {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 08c0a4b..cb99461 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -324,16 +324,16 @@
             }
             Display display = displayContent.getDisplay();
             mService.mDragState.register(display);
-            mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
             if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
-                    mService.mDragState.mServerChannel)) {
+                    mService.mDragState.getInputChannel())) {
                 Slog.e(TAG_WM, "Unable to transfer touch focus");
                 mService.mDragState.unregister();
+                mService.mDragState.reset();
                 mService.mDragState = null;
-                mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
                 return false;
             }
 
+            mService.mDragState.mDisplayContent = displayContent;
             mService.mDragState.mData = data;
             mService.mDragState.broadcastDragStartedLw(touchX, touchY);
             mService.mDragState.overridePointerIconLw(touchSource);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 6515fbd..34fa1b0 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -119,6 +119,8 @@
     // check if some got replaced and can be removed.
     private boolean mRemoveReplacedWindows = false;
 
+    private final AppTokenList mTmpExitingAppTokens = new AppTokenList();
+
     private String forceHidingToString() {
         switch (mForceHiding) {
             case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
@@ -189,10 +191,19 @@
                 }
             }
 
-            final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
-            final int exitingCount = exitingAppTokens.size();
+            mTmpExitingAppTokens.clear();
+            mTmpExitingAppTokens.addAll(stack.mExitingAppTokens);
+
+            final int exitingCount = mTmpExitingAppTokens.size();
             for (int i = 0; i < exitingCount; i++) {
-                final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
+                final AppWindowAnimator appAnimator = mTmpExitingAppTokens.get(i).mAppAnimator;
+                // stepAnimation can trigger finishExit->removeWindowInnerLocked
+                // ->performSurfacePlacement
+                // performSurfacePlacement will directly manipulate the mExitingAppTokens list
+                // so we need to iterate over a copy and check for modifications.
+                if (!stack.mExitingAppTokens.contains(appAnimator)) {
+                    continue;
+                }
                 appAnimator.wasAnimating = appAnimator.animating;
                 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
                     setAnimating(true);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8f7896e..22120d0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -771,9 +771,16 @@
         public void onInputEvent(InputEvent event) {
             boolean handled = false;
             try {
+                if (mDragState == null) {
+                    // The drag has ended but the clean-up message has not been processed by
+                    // window manager. Drop events that occur after this until window manager
+                    // has a chance to clean-up the input handle.
+                    handled = true;
+                    return;
+                }
                 if (event instanceof MotionEvent
                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
-                        && mDragState != null && !mMuteInput) {
+                        && !mMuteInput) {
                     final MotionEvent motionEvent = (MotionEvent)event;
                     boolean endDrag = false;
                     final float newX = motionEvent.getRawX();
@@ -833,6 +840,8 @@
                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
                         // tell all the windows that the drag has ended
                         synchronized (mWindowMap) {
+                            // endDragLw will post back to looper to dispose the receiver
+                            // since we still need the receiver for the last finishInputEvent.
                             mDragState.endDragLw();
                         }
                         mStylusButtonDownAtStart = false;
@@ -4718,6 +4727,12 @@
 
     // Called by window manager policy.  Not exposed externally.
     @Override
+    public void reboot(boolean confirm) {
+        ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+    }
+
+    // Called by window manager policy.  Not exposed externally.
+    @Override
     public void rebootSafeMode(boolean confirm) {
         ShutdownThread.rebootSafeMode(mContext, confirm);
     }
@@ -7099,6 +7114,7 @@
 
         public static final int RESIZE_STACK = 42;
         public static final int RESIZE_TASK = 43;
+        public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
 
         public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
 
@@ -7511,7 +7527,6 @@
                         // !!! TODO: ANR the app that has failed to start the drag in time
                         if (mDragState != null) {
                             mDragState.unregister();
-                            mInputMonitor.updateInputWindowsLw(true /*force*/);
                             mDragState.reset();
                             mDragState = null;
                         }
@@ -7534,6 +7549,17 @@
                     break;
                 }
 
+                case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
+                    if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel");
+                    DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
+                    if (interceptor != null) {
+                        synchronized (mWindowMap) {
+                            interceptor.tearDown();
+                        }
+                    }
+                }
+                break;
+
                 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
                     notifyHardKeyboardStatusChange();
                     break;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0fcf0c7..dfee8de 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -845,6 +845,22 @@
         mPendingDestroySurface = null;
     }
 
+    void applyMagnificationSpec(MagnificationSpec spec, Matrix transform) {
+        final int surfaceInsetLeft = mWin.mAttrs.surfaceInsets.left;
+        final int surfaceInsetTop = mWin.mAttrs.surfaceInsets.top;
+
+        if (spec != null && !spec.isNop()) {
+            float scale = spec.scale;
+            transform.postScale(scale, scale);
+            transform.postTranslate(spec.offsetX, spec.offsetY);
+
+            // As we are scaling the whole surface, to keep the content
+            // in the same position we will also have to scale the surfaceInsets.
+            transform.postTranslate(-(surfaceInsetLeft*scale - surfaceInsetLeft),
+                    -(surfaceInsetTop*scale - surfaceInsetTop));
+        }
+    }
+
     void computeShownFrameLocked() {
         final boolean selfTransformation = mHasLocalTransformation;
         Transformation attachedTransformation =
@@ -935,10 +951,7 @@
             if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
                 MagnificationSpec spec = mService.mAccessibilityController
                         .getMagnificationSpecForWindowLocked(mWin);
-                if (spec != null && !spec.isNop()) {
-                    tmpMatrix.postScale(spec.scale, spec.scale);
-                    tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
-                }
+                applyMagnificationSpec(spec, tmpMatrix);
             }
 
             // "convert" it into SurfaceFlinger's format
@@ -1037,10 +1050,7 @@
             tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
 
-            if (spec != null && !spec.isNop()) {
-                tmpMatrix.postScale(spec.scale, spec.scale);
-                tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
-            }
+            applyMagnificationSpec(spec, tmpMatrix);
 
             tmpMatrix.getValues(tmpFloats);
 
@@ -1896,11 +1906,13 @@
         if (mDeferTransactionUntilFrame < 0) {
             return;
         }
+        final WindowState parentWindow = mWin.getParentWindow();
         long time = System.currentTimeMillis();
         if (time > mDeferTransactionTime + PENDING_TRANSACTION_FINISH_WAIT_TIME) {
             mDeferTransactionTime = -1;
             mDeferTransactionUntilFrame = -1;
-        } else {
+        } else if (parentWindow != null &&
+                parentWindow.mWinAnimator.hasSurface()) {
             mSurfaceController.deferTransactionUntil(
                     mWin.getParentWindow().mWinAnimator.mSurfaceController.getHandle(),
                     mDeferTransactionUntilFrame);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index c26c078..4c9211a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1462,7 +1462,7 @@
             mObscured = true;
         }
 
-        if (w.mHasSurface) {
+        if (w.mHasSurface && canBeSeen) {
             if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
                 mHoldScreen = w.mSession;
                 mHoldScreenWindow = w;
@@ -1485,43 +1485,39 @@
             }
 
             final int type = attrs.type;
-            if (canBeSeen
-                    && (type == TYPE_SYSTEM_DIALOG
-                     || type == TYPE_SYSTEM_ERROR
-                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
+            if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
+                    || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                 mSyswin = true;
             }
 
-            if (canBeSeen) {
-                // This function assumes that the contents of the default display are
-                // processed first before secondary displays.
-                final DisplayContent displayContent = w.getDisplayContent();
-                if (displayContent != null && displayContent.isDefaultDisplay) {
-                    // While a dream or keyguard is showing, obscure ordinary application
-                    // content on secondary displays (by forcibly enabling mirroring unless
-                    // there is other content we want to show) but still allow opaque
-                    // keyguard dialogs to be shown.
-                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                        mObscureApplicationContentOnSecondaryDisplays = true;
-                    }
-                    mDisplayHasContent = true;
-                } else if (displayContent != null &&
-                        (!mObscureApplicationContentOnSecondaryDisplays
-                        || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
-                    // Allow full screen keyguard presentation dialogs to be seen.
-                    mDisplayHasContent = true;
+            // This function assumes that the contents of the default display are
+            // processed first before secondary displays.
+            final DisplayContent displayContent = w.getDisplayContent();
+            if (displayContent != null && displayContent.isDefaultDisplay) {
+                // While a dream or keyguard is showing, obscure ordinary application
+                // content on secondary displays (by forcibly enabling mirroring unless
+                // there is other content we want to show) but still allow opaque
+                // keyguard dialogs to be shown.
+                if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                    mObscureApplicationContentOnSecondaryDisplays = true;
                 }
-                if (mPreferredRefreshRate == 0
-                        && w.mAttrs.preferredRefreshRate != 0) {
-                    mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
-                }
-                if (mPreferredModeId == 0
-                        && w.mAttrs.preferredDisplayModeId != 0) {
-                    mPreferredModeId = w.mAttrs.preferredDisplayModeId;
-                }
-                if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
-                    mSustainedPerformanceModeCurrent = true;
-                }
+                mDisplayHasContent = true;
+            } else if (displayContent != null &&
+                    (!mObscureApplicationContentOnSecondaryDisplays
+                            || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
+                // Allow full screen keyguard presentation dialogs to be seen.
+                mDisplayHasContent = true;
+            }
+            if (mPreferredRefreshRate == 0
+                    && w.mAttrs.preferredRefreshRate != 0) {
+                mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
+            }
+            if (mPreferredModeId == 0
+                    && w.mAttrs.preferredDisplayModeId != 0) {
+                mPreferredModeId = w.mAttrs.preferredDisplayModeId;
+            }
+            if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
+                mSustainedPerformanceModeCurrent = true;
             }
         }
     }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f0cf320..548f831 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -810,10 +810,8 @@
 
                 traceBeginAndSlog("StartNetworkPolicyManagerService");
                 try {
-                    networkPolicy = new NetworkPolicyManagerService(
-                            context, mActivityManagerService,
-                            (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE),
-                            networkStats, networkManagement);
+                    networkPolicy = new NetworkPolicyManagerService(context,
+                            mActivityManagerService, networkStats, networkManagement);
                     ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
                 } catch (Throwable e) {
                     reportWtf("starting NetworkPolicy Service", e);
@@ -1013,6 +1011,10 @@
             mSystemServiceManager.startService(SoundTriggerService.class);
 
             if (!disableNonCoreServices) {
+                if (!disableTrustManager) {
+                    mSystemServiceManager.startService(TrustManagerService.class);
+                }
+
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BACKUP)) {
                     mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
                 }
@@ -1142,10 +1144,6 @@
                 }
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-                if (!disableTrustManager) {
-                    mSystemServiceManager.startService(TrustManagerService.class);
-                }
-
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
                     mSystemServiceManager.startService(FingerprintService.class);
                 }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 979f160..6247089 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,17 +16,12 @@
 
 package com.android.server;
 
-import static android.content.Intent.ACTION_UID_REMOVED;
-import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkPolicy.CYCLE_NONE;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
 import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
 import static android.net.TrafficStats.KB_IN_BYTES;
@@ -34,28 +29,42 @@
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.Time.TIMEZONE_UTC;
+
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
-import static org.easymock.EasyMock.anyInt;
-import static org.easymock.EasyMock.anyLong;
-import static org.easymock.EasyMock.aryEq;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
-import android.app.IProcessObserver;
+import android.app.IUidObserver;
 import android.app.Notification;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
-import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
@@ -69,40 +78,47 @@
 import android.net.NetworkTemplate;
 import android.os.Binder;
 import android.os.INetworkManagementService;
-import android.os.IPowerManager;
-import android.os.MessageQueue.IdleHandler;
+import android.os.PowerManagerInternal;
 import android.os.UserHandle;
-import android.test.AndroidTestCase;
-import android.test.mock.MockPackageManager;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
 import android.text.format.Time;
+import android.util.Log;
 import android.util.TrustedTime;
 
+import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.net.NetworkPolicyManagerService;
+
+import libcore.io.IoUtils;
+
 import com.google.common.util.concurrent.AbstractFuture;
 
-import org.easymock.Capture;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import java.io.File;
-import java.util.Calendar;
+import java.util.ArrayList;
 import java.util.LinkedHashSet;
-import java.util.TimeZone;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.logging.Handler;
-
-import libcore.io.IoUtils;
 
 /**
  * Tests for {@link NetworkPolicyManagerService}.
  */
-@LargeTest
-public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetworkPolicyManagerServiceTest {
     private static final String TAG = "NetworkPolicyManagerServiceTest";
 
     private static final long TEST_START = 1194220800000L;
@@ -114,20 +130,19 @@
     private BroadcastInterceptingContext mServiceContext;
     private File mPolicyDir;
 
-    private IActivityManager mActivityManager;
-    private IPowerManager mPowerManager;
-    private INetworkStatsService mStatsService;
-    private INetworkManagementService mNetworkManager;
-    private INetworkPolicyListener mPolicyListener;
-    private TrustedTime mTime;
-    private IConnectivityManager mConnManager;
-    private INotificationManager mNotifManager;
+    private @Mock IActivityManager mActivityManager;
+    private @Mock INetworkStatsService mStatsService;
+    private @Mock INetworkManagementService mNetworkManager;
+    private @Mock TrustedTime mTime;
+    private @Mock IConnectivityManager mConnManager;
+    private @Mock INotificationManager mNotifManager;
+    private @Mock PackageManager mPackageManager;
 
-    private NetworkPolicyManagerService mService;
-    private IProcessObserver mProcessObserver;
+    private IUidObserver mUidObserver;
     private INetworkManagementEventObserver mNetworkObserver;
 
-    private Binder mStubBinder = new Binder();
+    private NetworkPolicyListenerAnswer mPolicyListener;
+    private NetworkPolicyManagerService mService;
 
     private long mStartTime;
     private long mElapsedRealtime;
@@ -140,39 +155,30 @@
     private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
     private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
 
-    private static final int PID_1 = 400;
-    private static final int PID_2 = 401;
-    private static final int PID_3 = 402;
+    private static final String PKG_NAME_A = "name.is.A,pkg.A";
 
-    public void _setUp() throws Exception {
-        super.setUp();
+    @BeforeClass
+    public static void registerLocalServices() {
+        addLocalServiceMock(PowerManagerInternal.class);
+        addLocalServiceMock(DeviceIdleController.LocalService.class);
+        final UsageStatsManagerInternal usageStats =
+                addLocalServiceMock(UsageStatsManagerInternal.class);
+        when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
+    }
+
+    @Before
+    public void callSystemReady() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        final Context context = InstrumentationRegistry.getContext();
 
         setCurrentTimeMillis(TEST_START);
 
         // intercept various broadcasts, and pretend that uids have packages
-        mServiceContext = new BroadcastInterceptingContext(getContext()) {
+        mServiceContext = new BroadcastInterceptingContext(context) {
             @Override
             public PackageManager getPackageManager() {
-                return new MockPackageManager() {
-                    @Override
-                    public String[] getPackagesForUid(int uid) {
-                        return new String[] { "com.example" };
-                    }
-
-                    @Override
-                    public PackageInfo getPackageInfo(String packageName, int flags) {
-                        final PackageInfo info = new PackageInfo();
-                        final Signature signature;
-                        if ("android".equals(packageName)) {
-                            signature = new Signature("F00D");
-                        } else {
-                            signature = new Signature("DEAD");
-                        }
-                        info.signatures = new Signature[] { signature };
-                        return info;
-                    }
-
-                };
+                return mPackageManager;
             }
 
             @Override
@@ -181,275 +187,112 @@
             }
         };
 
-        mPolicyDir = getContext().getFilesDir();
+        mPolicyDir = context.getFilesDir();
         if (mPolicyDir.exists()) {
             IoUtils.deleteContents(mPolicyDir);
         }
 
-        mActivityManager = createMock(IActivityManager.class);
-        mPowerManager = createMock(IPowerManager.class);
-        mStatsService = createMock(INetworkStatsService.class);
-        mNetworkManager = createMock(INetworkManagementService.class);
-        mPolicyListener = createMock(INetworkPolicyListener.class);
-        mTime = createMock(TrustedTime.class);
-        mConnManager = createMock(IConnectivityManager.class);
-        mNotifManager = createMock(INotificationManager.class);
+        doAnswer(new Answer<Void>() {
 
-        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mPowerManager,
-                mStatsService, mNetworkManager, mTime, mPolicyDir, true);
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                mUidObserver = (IUidObserver) invocation.getArguments()[0];
+                Log.d(TAG, "set mUidObserver to " + mUidObserver);
+                return null;
+            }
+        }).when(mActivityManager).registerUidObserver(any(), anyInt());
+
+        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
+                mNetworkManager, mTime, mPolicyDir, true);
         mService.bindConnectivityManager(mConnManager);
         mService.bindNotificationManager(mNotifManager);
+        mPolicyListener = new NetworkPolicyListenerAnswer(mService);
 
-        // RemoteCallbackList needs a binder to use as key
-        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
-        replay();
-        mService.registerListener(mPolicyListener);
-        verifyAndReset();
+        // Sets some common expectations.
+        when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
+                new Answer<PackageInfo>() {
 
-        // catch IProcessObserver during systemReady()
-        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
-        mActivityManager.registerProcessObserver(capture(processObserver));
-        expectLastCall().atLeastOnce();
-
-        // catch INetworkManagementEventObserver during systemReady()
-        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
-                INetworkManagementEventObserver>();
-        mNetworkManager.registerObserver(capture(networkObserver));
-        expectLastCall().atLeastOnce();
-
-        // expect to answer screen status during systemReady()
-        expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
-        expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
+                    @Override
+                    public PackageInfo answer(InvocationOnMock invocation) throws Throwable {
+                        final String packageName = (String) invocation.getArguments()[0];
+                        final PackageInfo info = new PackageInfo();
+                        final Signature signature;
+                        if ("android".equals(packageName)) {
+                            signature = new Signature("F00D");
+                        } else {
+                            signature = new Signature("DEAD");
+                        }
+                        info.signatures = new Signature[] {
+                            signature
+                        };
+                        return info;
+                    }
+                });
+        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(new ApplicationInfo());
+        when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
+        when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
         expectCurrentTime();
 
-        replay();
+        // Prepare NPMS.
         mService.systemReady();
-        verifyAndReset();
 
-        mProcessObserver = processObserver.getValue();
+        // catch INetworkManagementEventObserver during systemReady()
+        ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
+              ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+        verify(mNetworkManager).registerObserver(networkObserver.capture());
         mNetworkObserver = networkObserver.getValue();
-
     }
 
-    public void _tearDown() throws Exception {
+    @After
+    public void removeFiles() throws Exception {
         for (File file : mPolicyDir.listFiles()) {
             file.delete();
         }
-
-        mServiceContext = null;
-        mPolicyDir = null;
-
-        mActivityManager = null;
-        mPowerManager = null;
-        mStatsService = null;
-        mPolicyListener = null;
-        mTime = null;
-
-        mService = null;
-        mProcessObserver = null;
-
-        super.tearDown();
     }
 
-    @Suppress
-    public void testPolicyChangeTriggersBroadcast() throws Exception {
+    @After
+    public void unregisterLocalServices() throws Exception {
+        // Registered by NetworkPolicyManagerService's constructor.
+        LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
+    }
+
+    // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they
+    // don't check for side-effects (like calls to NetworkManagementService) neither cover all
+    // different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
+    // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
+
+    @Test
+    public void testPolicyChangeTriggersListener() throws Exception {
+        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
+
         mService.setUidPolicy(APP_ID_A, POLICY_NONE);
-
-        // change background policy and expect broadcast
-        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
-                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
-
         mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
 
-        backgroundChanged.get();
+        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
     }
 
-    @Suppress
-    public void testPidForegroundCombined() throws Exception {
-        IdleFuture idle;
-
-        // push all uid into background
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
-        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
-        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
-        idle.get();
+    @Test
+    public void testUidForeground() throws Exception {
+        // push all uids into background
+        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+        mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
         assertFalse(mService.isUidForeground(UID_A));
         assertFalse(mService.isUidForeground(UID_B));
 
-        // push one of the shared pids into foreground
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
-        idle.get();
+        // push one of the uids into foreground
+        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
         assertTrue(mService.isUidForeground(UID_A));
         assertFalse(mService.isUidForeground(UID_B));
 
         // and swap another uid into foreground
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
-        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
-        idle.get();
+        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+        mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
         assertFalse(mService.isUidForeground(UID_A));
         assertTrue(mService.isUidForeground(UID_B));
-
-        // push both pid into foreground
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
-        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
-        idle.get();
-        assertTrue(mService.isUidForeground(UID_A));
-
-        // pull one out, should still be foreground
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
-        idle.get();
-        assertTrue(mService.isUidForeground(UID_A));
-
-        // pull final pid out, should now be background
-        idle = expectIdle();
-        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
-        idle.get();
-        assertFalse(mService.isUidForeground(UID_A));
     }
 
-    @Suppress
-    public void testScreenChangesRules() throws Exception {
-        Future<Void> future;
-
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, true);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
-        future.get();
-        verifyAndReset();
-
-        // push strict policy for foreground uid, verify ALLOW rule
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, true);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
-        future.get();
-        verifyAndReset();
-
-        // now turn screen off and verify REJECT rule
-        expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce();
-        expectSetUidMeteredNetworkBlacklist(UID_A, true);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        replay();
-        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
-        future.get();
-        verifyAndReset();
-
-        // and turn screen back on, verify ALLOW rule restored
-        expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, true);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
-        future.get();
-        verifyAndReset();
-    }
-
-    @Suppress
-    public void testPolicyNone() throws Exception {
-        Future<Void> future;
-
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, true);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
-        future.get();
-        verifyAndReset();
-
-        // POLICY_NONE should RULE_ALLOW in foreground
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, true);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
-        future.get();
-        verifyAndReset();
-
-        // POLICY_NONE should RULE_ALLOW in background
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
-        future.get();
-        verifyAndReset();
-    }
-
-    @Suppress
-    public void testPolicyReject() throws Exception {
-        Future<Void> future;
-
-        // POLICY_REJECT should RULE_ALLOW in background
-        expectSetUidMeteredNetworkBlacklist(UID_A, true);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        replay();
-        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
-        future.get();
-        verifyAndReset();
-
-        // POLICY_REJECT should RULE_ALLOW in foreground
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, true);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
-        future.get();
-        verifyAndReset();
-
-        // POLICY_REJECT should RULE_REJECT in background
-        expectSetUidMeteredNetworkBlacklist(UID_A, true);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        replay();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
-        future.get();
-        verifyAndReset();
-    }
-
-    @Suppress
-    public void testPolicyRejectAddRemove() throws Exception {
-        Future<Void> future;
-
-        // POLICY_NONE should have RULE_ALLOW in background
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
-        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
-        future.get();
-        verifyAndReset();
-
-        // adding POLICY_REJECT should cause RULE_REJECT
-        expectSetUidMeteredNetworkBlacklist(UID_A, true);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        replay();
-        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
-        future.get();
-        verifyAndReset();
-
-        // removing POLICY_REJECT should return us to RULE_ALLOW
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
-        future.get();
-        verifyAndReset();
-    }
-
+    @Test
     public void testLastCycleBoundaryThisMonth() throws Exception {
         // assume cycle day of "5th", which should be in same month
         final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -461,6 +304,7 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
+    @Test
     public void testLastCycleBoundaryLastMonth() throws Exception {
         // assume cycle day of "20th", which should be in last month
         final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -472,6 +316,7 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
+    @Test
     public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
         // assume cycle day of "30th" in february; should go to january
         final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
@@ -483,6 +328,7 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
+    @Test
     public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
         // assume cycle day of "30th" in february, which should clamp
         final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
@@ -494,6 +340,7 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
+    @Test
     public void testCycleBoundaryLeapYear() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false);
@@ -517,6 +364,7 @@
                 computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
     }
 
+    @Test
     public void testNextCycleTimezoneAfterUtc() throws Exception {
         // US/Central is UTC-6
         final NetworkPolicy policy = new NetworkPolicy(
@@ -525,6 +373,7 @@
                 computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
     }
 
+    @Test
     public void testNextCycleTimezoneBeforeUtc() throws Exception {
         // Israel is UTC+2
         final NetworkPolicy policy = new NetworkPolicy(
@@ -533,6 +382,7 @@
                 computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
     }
 
+    @Test
     public void testNextCycleSane() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -548,6 +398,7 @@
         }
     }
 
+    @Test
     public void testLastCycleSane() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -563,6 +414,7 @@
         }
     }
 
+    @Test
     public void testCycleTodayJanuary() throws Exception {
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
@@ -582,6 +434,7 @@
                 computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
     }
 
+    @Test
     public void testLastCycleBoundaryDST() throws Exception {
         final long currentTime = parseTime("1989-01-02T07:30:00.000");
         final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z");
@@ -592,11 +445,10 @@
         assertTimeEquals(expectedCycle, actualCycle);
     }
 
-    @Suppress
+    @Test
     public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
-        Future<Void> future;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -607,75 +459,40 @@
         // first, pretend that wifi network comes online. no policy active,
         // which means we shouldn't push limit to interface.
         state = new NetworkState[] { buildWifi() };
-        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+        when(mConnManager.getAllNetworkState()).thenReturn(state);
         expectCurrentTime();
-        expectClearNotifications();
-        expectAdvisePersistThreshold();
-        future = expectMeteredIfacesChanged();
 
-        replay();
+        mPolicyListener.expect().onMeteredIfacesChanged(any());
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
-        future.get();
-        verifyAndReset();
+        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
 
         // now change cycle to be on 15th, and test in early march, to verify we
         // pick cycle day in previous month.
-        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+        when(mConnManager.getAllNetworkState()).thenReturn(state);
         expectCurrentTime();
 
         // pretend that 512 bytes total have happened
         stats = new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
-        expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
-                .andReturn(stats.getTotalBytes()).atLeastOnce();
-        expectPolicyDataEnable(TYPE_WIFI, true);
+        when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+                .thenReturn(stats.getTotalBytes());
 
-        // TODO: consider making strongly ordered mock
-        expectRemoveInterfaceQuota(TEST_IFACE);
-        expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
-
-        expectClearNotifications();
-        expectAdvisePersistThreshold();
-        future = expectMeteredIfacesChanged(TEST_IFACE);
-
-        replay();
+        mPolicyListener.expect().onMeteredIfacesChanged(any());
         setNetworkPolicies(new NetworkPolicy(
                 sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
-        future.get();
-        verifyAndReset();
+        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+        // TODO: consider making strongly ordered mock
+        verifyPolicyDataEnable(TYPE_WIFI, true);
+        verifyRemoveInterfaceQuota(TEST_IFACE);
+        verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
     }
 
-    @Suppress
-    public void testUidRemovedPolicyCleared() throws Exception {
-        Future<Void> future;
-
-        // POLICY_REJECT should RULE_REJECT in background
-        expectSetUidMeteredNetworkBlacklist(UID_A, true);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        replay();
-        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
-        future.get();
-        verifyAndReset();
-
-        // uninstall should clear RULE_REJECT
-        expectSetUidMeteredNetworkBlacklist(UID_A, false);
-        expectSetUidForeground(UID_A, false);
-        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        replay();
-        final Intent intent = new Intent(ACTION_UID_REMOVED);
-        intent.putExtra(EXTRA_UID, UID_A);
-        mServiceContext.sendBroadcast(intent);
-        future.get();
-        verifyAndReset();
-    }
-
-    @Suppress
+    @Test
     public void testOverWarningLimitNotification() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
-        Future<Void> future;
-        Future<String> tagFuture;
+        Future<String> tagFuture = null;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -690,20 +507,15 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
 
-            expectClearNotifications();
-            expectAdvisePersistThreshold();
-            future = expectMeteredIfacesChanged();
-
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
                     * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
-            future.get();
-            verifyAndReset();
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
+            verifyPolicyDataEnable(TYPE_WIFI, true);
         }
 
         // bring up wifi network
@@ -714,22 +526,17 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
 
-            expectRemoveInterfaceQuota(TEST_IFACE);
-            expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
-
-            expectClearNotifications();
-            expectAdvisePersistThreshold();
-            future = expectMeteredIfacesChanged(TEST_IFACE);
-
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
-            future.get();
-            verifyAndReset();
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+            verifyPolicyDataEnable(TYPE_WIFI, true);
+            verifyRemoveInterfaceQuota(TEST_IFACE);
+            verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
         }
 
         // go over warning, which should kick notification
@@ -739,18 +546,15 @@
 
         {
             expectCurrentTime();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
-
-            expectForceUpdate();
-            expectClearNotifications();
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
             tagFuture = expectEnqueueNotification();
 
-            replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
+
             assertNotificationType(TYPE_WARNING, tagFuture.get());
-            verifyAndReset();
+            verifyPolicyDataEnable(TYPE_WIFI, true);
+
         }
 
         // go over limit, which should kick notification and dialog
@@ -760,18 +564,14 @@
 
         {
             expectCurrentTime();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, false);
-
-            expectForceUpdate();
-            expectClearNotifications();
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
             tagFuture = expectEnqueueNotification();
 
-            replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
+
             assertNotificationType(TYPE_LIMIT, tagFuture.get());
-            verifyAndReset();
+            verifyPolicyDataEnable(TYPE_WIFI, false);
         }
 
         // now snooze policy, which should remove quota
@@ -779,35 +579,28 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
-
-            // snoozed interface still has high quota so background data is
-            // still restricted.
-            expectRemoveInterfaceQuota(TEST_IFACE);
-            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-            expectAdvisePersistThreshold();
-            expectMeteredIfacesChanged(TEST_IFACE);
-
-            future = expectClearNotifications();
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
             tagFuture = expectEnqueueNotification();
 
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             mService.snoozeLimit(sTemplateWifi);
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
             assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
-            future.get();
-            verifyAndReset();
+            // snoozed interface still has high quota so background data is
+            // still restricted.
+            verifyRemoveInterfaceQuota(TEST_IFACE);
+            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+            verifyPolicyDataEnable(TYPE_WIFI, true);
         }
     }
 
-    @Suppress
+    @Test
     public void testMeteredNetworkWithoutLimit() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
-        Future<Void> future;
-        Future<String> tagFuture;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -822,24 +615,19 @@
 
         {
             expectCurrentTime();
-            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats.getTotalBytes()).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true);
+            when(mConnManager.getAllNetworkState()).thenReturn(state);
+            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
 
-            expectRemoveInterfaceQuota(TEST_IFACE);
-            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-
-            expectClearNotifications();
-            expectAdvisePersistThreshold();
-            future = expectMeteredIfacesChanged(TEST_IFACE);
-
-            replay();
+            mPolicyListener.expect().onMeteredIfacesChanged(any());
             setNetworkPolicies(new NetworkPolicy(
                     sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
                     true));
-            future.get();
-            verifyAndReset();
+            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+            verifyPolicyDataEnable(TYPE_WIFI, true);
+            verifyRemoveInterfaceQuota(TEST_IFACE);
+            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
         }
     }
 
@@ -862,87 +650,36 @@
     }
 
     private void expectCurrentTime() throws Exception {
-        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
-        expect(mTime.hasCache()).andReturn(true).anyTimes();
-        expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
-        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
-        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
-    }
-
-    private void expectForceUpdate() throws Exception {
-        mStatsService.forceUpdate();
-        expectLastCall().atLeastOnce();
-    }
-
-    private Future<Void> expectClearNotifications() throws Exception {
-        final FutureAnswer future = new FutureAnswer();
-        mNotifManager.cancelNotificationWithTag(
-                isA(String.class), isA(String.class), anyInt(), anyInt());
-        expectLastCall().andAnswer(future).anyTimes();
-        return future;
+        when(mTime.forceRefresh()).thenReturn(false);
+        when(mTime.hasCache()).thenReturn(true);
+        when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
+        when(mTime.getCacheAge()).thenReturn(0L);
+        when(mTime.getCacheCertainty()).thenReturn(0L);
     }
 
     private Future<String> expectEnqueueNotification() throws Exception {
-        final FutureCapture<String> tag = new FutureCapture<String>();
-        mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class),
-                capture(tag.capture), anyInt(),
-                isA(Notification.class), isA(int[].class), UserHandle.myUserId());
-        return tag;
+        final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2);
+        doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag(
+                anyString(), anyString(), anyString() /* capture here (index 2)*/,
+                anyInt(), isA(Notification.class), isA(int[].class), anyInt());
+        return futureAnswer;
     }
 
-    private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
-        mNetworkManager.setInterfaceQuota(iface, quotaBytes);
-        expectLastCall().atLeastOnce();
+    private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+        verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
     }
 
-    private void expectRemoveInterfaceQuota(String iface) throws Exception {
-        mNetworkManager.removeInterfaceQuota(iface);
-        expectLastCall().atLeastOnce();
+    private void verifyRemoveInterfaceQuota(String iface) throws Exception {
+        verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
     }
 
-    private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
-        mNetworkManager.setInterfaceAlert(iface, alertBytes);
-        expectLastCall().atLeastOnce();
-    }
-
-    private void expectRemoveInterfaceAlert(String iface) throws Exception {
-        mNetworkManager.removeInterfaceAlert(iface);
-        expectLastCall().atLeastOnce();
-    }
-
-    private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces)
-            throws Exception {
-        mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
-        expectLastCall().atLeastOnce();
-    }
-
-    private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception {
-        mStatsService.setUidForeground(uid, uidForeground);
-        expectLastCall().atLeastOnce();
-    }
-
-    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
-        final FutureAnswer future = new FutureAnswer();
-        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
-        expectLastCall().andAnswer(future);
-        return future;
-    }
-
-    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
-        final FutureAnswer future = new FutureAnswer();
-        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
-        expectLastCall().andAnswer(future);
-        return future;
-    }
-
-    private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
+    private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
         // TODO: bring back this test
         return null;
     }
 
-    private void expectAdvisePersistThreshold() throws Exception {
-        mStatsService.advisePersistThreshold(anyLong());
-        expectLastCall().anyTimes();
+    private void verifyAdvisePersistThreshold() throws Exception {
+        verify(mStatsService).advisePersistThreshold(anyLong());
     }
 
     private static class TestAbstractFuture<T> extends AbstractFuture<T> {
@@ -956,50 +693,21 @@
         }
     }
 
-    private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
+    private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
+        private final int index;
+
+        FutureAnswer(int index) {
+            this.index = index;
+        }
         @Override
-        public Void answer() {
-            set(null);
+        public Void answer(InvocationOnMock invocation) throws Throwable {
+            @SuppressWarnings("unchecked")
+            T captured = (T) invocation.getArguments()[index];
+            set(captured);
             return null;
         }
     }
 
-    private static class FutureCapture<T> extends TestAbstractFuture<T> {
-        public Capture<T> capture = new Capture<T>() {
-            @Override
-            public void setValue(T value) {
-                super.setValue(value);
-                set(value);
-            }
-        };
-    }
-
-    private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
-        @Override
-        public Void get() throws InterruptedException, ExecutionException {
-            try {
-                return get(5, TimeUnit.SECONDS);
-            } catch (TimeoutException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        @Override
-        public boolean queueIdle() {
-            set(null);
-            return false;
-        }
-    }
-
-    /**
-     * Wait until {@link #mService} internal {@link Handler} is idle.
-     */
-    private IdleFuture expectIdle() {
-        final IdleFuture future = new IdleFuture();
-        mService.addIdleHandler(future);
-        return future;
-    }
-
     private static void assertTimeEquals(long expected, long actual) {
         if (expected != actual) {
             fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
@@ -1027,7 +735,7 @@
     }
 
     private static void assertNotificationType(int expected, String actualTag) {
-        assertEquals(
+        assertEquals("notification type mismatch for '" + actualTag +"'",
                 Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
     }
 
@@ -1048,15 +756,59 @@
         mElapsedRealtime += duration;
     }
 
-    private void replay() {
-        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
-                mNetworkManager, mTime, mConnManager, mNotifManager);
+    /**
+     * Creates a mock and registers it to {@link LocalServices}.
+     */
+    private static <T> T addLocalServiceMock(Class<T> clazz) {
+        final T mock = mock(clazz);
+        LocalServices.addService(clazz, mock);
+        return mock;
     }
 
-    private void verifyAndReset() {
-        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
-                mNetworkManager, mTime, mConnManager, mNotifManager);
-        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
-                mNetworkManager, mTime, mConnManager, mNotifManager);
+    /**
+     * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
+     *
+     * <p>Typical usage:
+     * <pre><code>
+     *    mPolicyListener.expect().someCallback(any());
+     *    // do something on objects under test
+     *    mPolicyListener.waitAndVerify().someCallback(eq(expectedValue));
+     * </code></pre>
+     */
+    final class NetworkPolicyListenerAnswer implements Answer<Void> {
+        private CountDownLatch latch;
+        private final INetworkPolicyListener listener;
+
+        NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) {
+            this.listener = mock(INetworkPolicyListener.class);
+            // RemoteCallbackList needs a binder to use as key
+            when(listener.asBinder()).thenReturn(new Binder());
+            service.registerListener(listener);
+        }
+
+        @Override
+        public Void answer(InvocationOnMock invocation) throws Throwable {
+            Log.d(TAG,"counting down on answer: " + invocation);
+            latch.countDown();
+            return null;
+        }
+
+        INetworkPolicyListener expect() {
+            assertNull("expect() called before waitAndVerify()", latch);
+            latch = new CountDownLatch(1);
+            return doAnswer(this).when(listener);
+        }
+
+        INetworkPolicyListener waitAndVerify() {
+            assertNotNull("waitAndVerify() called before expect()", latch);
+            try {
+                assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS));
+            } catch (InterruptedException e) {
+                fail("Thread interrupted before callback called");
+            } finally {
+                latch = null;
+            }
+            return verify(listener, atLeastOnce());
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index e7f3345..1c7a138 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -247,20 +247,6 @@
         }
 
         @Override
-        protected boolean isUserUnlockedL(@UserIdInt int userId) {
-            // Note due to a late change, now ShortcutManager doesn't use
-            // UserManager.isUserUnlockingOrUnlocked().  But all unit tests are still using it,
-            // so we convert here.
-
-            final long token = injectClearCallingIdentity();
-            try {
-                return mMockUserManager.isUserUnlockingOrUnlocked(userId);
-            } finally {
-                injectRestoreCallingIdentity(token);
-            }
-        }
-
-        @Override
         int injectDipToPixel(int dip) {
             return dip;
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
index ba83be1..64c5622 100644
--- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
@@ -39,7 +39,7 @@
     public PackageSetting generateFakePackageSetting(String name) {
         return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"),
                 new File(mContext.getCacheDir(), "fakeResPath"), "", "", "",
-                "", 1, 0, 0, null, null);
+                "", 1, 0, 0, null, null, 0 /*sharedUserId*/);
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index a939134..09bd12c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -522,7 +522,8 @@
                 pkgFlags,
                 0 /*privateFlags*/,
                 null /*parentPackageName*/,
-                null /*childPackageNames*/);
+                null /*childPackageNames*/,
+                0 /*sharedUserId*/);
     }
 
     private @NonNull List<UserInfo> createFakeUsers() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 75a3427..253334e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -5863,6 +5863,7 @@
             assertEmpty(mManager.getPinnedShortcuts());
         });
         // Send add broadcast, but the user is not running, so should be ignored.
+        mService.handleCleanupUser(USER_10);
         mRunningUsers.put(USER_10, false);
         mUnlockedUsers.put(USER_10, false);
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index ad5bc77..d25923c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -2005,4 +2005,36 @@
                     });
         });
     }
+
+    public void testIsUserUnlocked() {
+        mRunningUsers.clear();
+        mUnlockedUsers.clear();
+
+        assertFalse(mService.isUserUnlockedL(USER_0));
+        assertFalse(mService.isUserUnlockedL(USER_10));
+
+        // Start user 0, still locked.
+        mRunningUsers.put(USER_0, true);
+        assertFalse(mService.isUserUnlockedL(USER_0));
+        assertFalse(mService.isUserUnlockedL(USER_10));
+
+        // Unlock user.
+        mUnlockedUsers.put(USER_0, true);
+        assertTrue(mService.isUserUnlockedL(USER_0));
+        assertFalse(mService.isUserUnlockedL(USER_10));
+
+        // Clear again.
+        mRunningUsers.clear();
+        mUnlockedUsers.clear();
+
+        // Directly call the lifecycle event.  Now also locked.
+        mService.handleUnlockUser(USER_0);
+        assertTrue(mService.isUserUnlockedL(USER_0));
+        assertFalse(mService.isUserUnlockedL(USER_10));
+
+        // Directly call the stop lifecycle event.  Goes back to the initial state.
+        mService.handleCleanupUser(USER_0);
+        assertFalse(mService.isUserUnlockedL(USER_0));
+        assertFalse(mService.isUserUnlockedL(USER_10));
+    }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 8560651..efd479f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -563,6 +563,7 @@
                             mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
 
             if (mConfigured && enteringAccessoryMode) {
+                mAccessoryModeRequestTime = 0;
                 // successfully entered accessory mode
 
                 if (mAccessoryStrings != null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index b0cc2ac..c3075b3 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -46,6 +46,7 @@
 import android.view.IWindowManager;
 import android.view.WindowManager;
 
+import com.android.internal.app.AssistUtils;
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
@@ -301,7 +302,7 @@
             } else {
                 mScreenshot = null;
             }
-            if (needDisclosure) {
+            if (needDisclosure && AssistUtils.shouldDisclose(mContext, mSessionComponentName)) {
                 mHandler.post(mShowAssistDisclosureRunnable);
             }
             if (mSession != null) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 68a6166..e666986 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -906,6 +906,19 @@
     public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL =
             "enhanced_4g_lte_title_variant_bool";
 
+    /**
+     * Indicates whether the carrier wants to notify the user when handover of an LTE video call to
+     * WIFI fails.
+     * <p>
+     * When {@code true}, if a video call starts on LTE and the modem reports a failure to handover
+     * the call to WIFI or if no handover success is reported within 60 seconds of call initiation,
+     * the {@link android.telephony.TelephonyManager#EVENT_HANDOVER_TO_WIFI_FAILED} event is raised
+     * on the connection.
+     * @hide
+     */
+    public static final String KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL =
+            "notify_vt_handover_to_wifi_failure_bool";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -1071,6 +1084,7 @@
 
         sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL, false);
+        sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index d7d4e84..f5e422d 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -212,6 +212,20 @@
      */
     public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53;
 
+    /**
+     * The call was terminated because cellular data has been disabled.
+     * Used when in a video call and the user disables cellular data via the settings.
+     * {@hide}
+     */
+    public static final int DATA_DISABLED = 54;
+
+    /**
+     * The call was terminated because the data policy has disabled cellular data.
+     * Used when in a video call and the user has exceeded the device data limit.
+     * {@hide}
+     */
+    public static final int DATA_LIMIT_REACHED = 55;
+
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Please assign the new type the next id value below.
@@ -220,14 +234,14 @@
     // 4) Update toString() with the newly added disconnect type.
     // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
     //
-    // NextId: 54
+    // NextId: 56
     //*********************************************************************************************
 
     /** Smallest valid value for call disconnect codes. */
     public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
 
     /** Largest valid value for call disconnect codes. */
-    public static final int MAXIMUM_VALID_VALUE = MAXIMUM_NUMBER_OF_CALLS_REACHED;
+    public static final int MAXIMUM_VALID_VALUE = DATA_LIMIT_REACHED;
 
     /** Private constructor to avoid class instantiation. */
     private DisconnectCause() {
@@ -343,6 +357,10 @@
             return "ANSWERED_ELSEWHERE";
         case MAXIMUM_NUMBER_OF_CALLS_REACHED:
             return "MAXIMUM_NUMER_OF_CALLS_REACHED";
+        case DATA_DISABLED:
+            return "DATA_DISABLED";
+        case DATA_LIMIT_REACHED:
+            return "DATA_LIMIT_REACHED";
         default:
             return "INVALID: " + cause;
         }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fed9e71..4138aa0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2484,6 +2484,56 @@
     }
 
     /**
+     * Enables or disables the visual voicemail client for a phone account.
+     *
+     * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
+     * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     * @see #hasCarrierPrivileges
+     *
+     * @param phoneAccountHandle the phone account to change the client state
+     * @param enabled the new state of the client
+     * @hide
+     */
+    @SystemApi
+    public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.setVisualVoicemailEnabled(mContext.getOpPackageName(), phoneAccountHandle,
+                    enabled);
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+        }
+    }
+
+    /**
+     * Returns whether the visual voicemail client is enabled.
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     *
+     * @param phoneAccountHandle the phone account to check for.
+     * @return {@code true} when the visual voicemail client is enabled for this client
+     * @hide
+     */
+    @SystemApi
+    public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isVisualVoicemailEnabled(
+                    mContext.getOpPackageName(), phoneAccountHandle);
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+        }
+        return false;
+    }
+
+    /**
      * Enables the visual voicemail SMS filter for a phone account. When the filter is
      * enabled, Incoming SMS messages matching the OMTP VVM SMS interface will be redirected to the
      * visual voicemail client with
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 408ad31..56b8822 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -298,6 +298,16 @@
     public static final int CODE_REMOTE_CALL_DECLINE = 1404;
 
     /**
+     * Indicates the call was disconnected due to the user reaching their data limit.
+     */
+    public static final int CODE_DATA_LIMIT_REACHED = 1405;
+
+    /**
+     * Indicates the call was disconnected due to the user disabling cellular data.
+     */
+    public static final int CODE_DATA_DISABLED = 1406;
+
+    /**
      * Network string error messages.
      * mExtraMessage may have these values.
      */
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 7e7071e..a8eaf36 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -454,6 +454,12 @@
      */
     int getVoiceMessageCountForSubscriber(int subId);
 
+    oneway void setVisualVoicemailEnabled(String callingPackage,
+            in PhoneAccountHandle accountHandle, boolean enabled);
+
+    boolean isVisualVoicemailEnabled(String callingPackage,
+            in PhoneAccountHandle accountHandle);
+
     // Not oneway, caller needs to make sure the vaule is set before receiving a SMS
     void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
             in VisualVoicemailSmsFilterSettings settings);
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index c1cfd0b..3c3edda 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1309,8 +1309,8 @@
 
 status_t AaptAssets::filter(Bundle* bundle)
 {
-    WeakResourceFilter reqFilter;
-    status_t err = reqFilter.parse(bundle->getConfigurations());
+    sp<WeakResourceFilter> reqFilter(new WeakResourceFilter());
+    status_t err = reqFilter->parse(bundle->getConfigurations());
     if (err != NO_ERROR) {
         return err;
     }
@@ -1326,12 +1326,12 @@
         preferredDensity = preferredConfig.density;
     }
 
-    if (reqFilter.isEmpty() && preferredDensity == 0) {
+    if (reqFilter->isEmpty() && preferredDensity == 0) {
         return NO_ERROR;
     }
 
     if (bundle->getVerbose()) {
-        if (!reqFilter.isEmpty()) {
+        if (!reqFilter->isEmpty()) {
             printf("Applying required filter: %s\n",
                     bundle->getConfigurations().string());
         }
@@ -1383,7 +1383,7 @@
                     continue;
                 }
                 const ResTable_config& config(file->getGroupEntry().toParams());
-                if (!reqFilter.match(config)) {
+                if (!reqFilter->match(config)) {
                     if (bundle->getVerbose()) {
                         printf("Pruning unneeded resource: %s\n",
                                 file->getPrintableSource().string());
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 4fdc964..eadd48a 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -103,7 +103,7 @@
 {
 public:
     AaptGroupEntry() {}
-    AaptGroupEntry(const ConfigDescription& config) : mParams(config) {}
+    explicit AaptGroupEntry(const ConfigDescription& config) : mParams(config) {}
 
     bool initFromDirName(const char* dir, String8* resType);
 
@@ -312,7 +312,7 @@
         : isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
     {
     }
-    AaptSymbolEntry(const String8& _name)
+    explicit AaptSymbolEntry(const String8& _name)
         : name(_name), isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
     {
     }
diff --git a/tools/aapt/ApkBuilder.h b/tools/aapt/ApkBuilder.h
index 0d7f06b..5d3abc6 100644
--- a/tools/aapt/ApkBuilder.h
+++ b/tools/aapt/ApkBuilder.h
@@ -32,7 +32,7 @@
 
 class ApkBuilder : public android::RefBase {
 public:
-    ApkBuilder(const sp<WeakResourceFilter>& configFilter);
+    explicit ApkBuilder(const sp<WeakResourceFilter>& configFilter);
 
     /**
      * Tells the builder to generate a separate APK for resources that
diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h
index 10a1bbc..6fa96d6 100644
--- a/tools/aapt/CacheUpdater.h
+++ b/tools/aapt/CacheUpdater.h
@@ -51,7 +51,7 @@
 class SystemCacheUpdater : public CacheUpdater {
 public:
     // Constructor to set bundle to pass to preProcessImage
-    SystemCacheUpdater (Bundle* b)
+    explicit SystemCacheUpdater (Bundle* b)
         : bundle(b) { };
 
     // Make sure all the directories along this path exist
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index cbad4b9..d80aaba 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -248,7 +248,7 @@
 }
 
 static void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
-        uint32_t attrRes, String8 attrLabel, String8* outError)
+        uint32_t attrRes, const String8& attrLabel, String8* outError)
 {
     Res_value value;
     AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
@@ -399,7 +399,7 @@
             ResTable::normalizeForOutput(reason.string()).string());
 }
 
-Vector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
+Vector<String8> getNfcAidCategories(AssetManager& assets, const String8& xmlPath, bool offHost,
         String8 *outError = NULL)
 {
     Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h
index 4f999a2..09430f2 100644
--- a/tools/aapt/ConfigDescription.h
+++ b/tools/aapt/ConfigDescription.h
@@ -29,7 +29,7 @@
         size = sizeof(android::ResTable_config);
     }
 
-    ConfigDescription(const android::ResTable_config&o) {
+    ConfigDescription(const android::ResTable_config&o) {  // NOLINT(implicit)
         *static_cast<android::ResTable_config*>(this) = o;
         size = sizeof(android::ResTable_config);
     }
diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp
index 0d574cf..7b8a576 100644
--- a/tools/aapt/CrunchCache.cpp
+++ b/tools/aapt/CrunchCache.cpp
@@ -94,7 +94,7 @@
     delete dw;
 }
 
-bool CrunchCache::needsUpdating(String8 relativePath) const
+bool CrunchCache::needsUpdating(const String8& relativePath) const
 {
     // Retrieve modification dates for this file entry under the source and
     // cache directory trees. The vectors will return a modification date of 0
diff --git a/tools/aapt/CrunchCache.h b/tools/aapt/CrunchCache.h
index be3da5c..4d6a169 100644
--- a/tools/aapt/CrunchCache.h
+++ b/tools/aapt/CrunchCache.h
@@ -81,7 +81,7 @@
      *          // Recrunch sourceFile out to destFile.
      *
      */
-    bool needsUpdating(String8 relativePath) const;
+    bool needsUpdating(const String8& relativePath) const;
 
     // DATA MEMBERS ====================================================
 
diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp
index 18775c0..c9d0744 100644
--- a/tools/aapt/FileFinder.cpp
+++ b/tools/aapt/FileFinder.cpp
@@ -77,7 +77,7 @@
     return true;
 }
 
-void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
+void SystemFileFinder::checkAndAddFile(const String8& path, const struct stat* stats,
                                        Vector<String8>& extensions,
                                        KeyedVector<String8,time_t>& fileStore)
 {
diff --git a/tools/aapt/FileFinder.h b/tools/aapt/FileFinder.h
index 6974aee..f405381 100644
--- a/tools/aapt/FileFinder.h
+++ b/tools/aapt/FileFinder.h
@@ -72,7 +72,7 @@
      *    time as the value.
      *
      */
-    static void checkAndAddFile(String8 path, const struct stat* stats,
+    static void checkAndAddFile(const String8& path, const struct stat* stats,
                                 Vector<String8>& extensions,
                                 KeyedVector<String8,time_t>& fileStore);
 
diff --git a/tools/aapt/IndentPrinter.h b/tools/aapt/IndentPrinter.h
index 6fc94bc..bd0edcb 100644
--- a/tools/aapt/IndentPrinter.h
+++ b/tools/aapt/IndentPrinter.h
@@ -3,7 +3,7 @@
 
 class IndentPrinter {
 public:
-    IndentPrinter(FILE* stream, int indentSize=2)
+    explicit IndentPrinter(FILE* stream, int indentSize=2)
         : mStream(stream)
         , mIndentSize(indentSize)
         , mIndent(0)
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index b278831..b4c4d05 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -399,7 +399,7 @@
     const DefaultKeyedVector<String8, sp<AaptGroup> >& groups = dir->getFiles();
     int N = groups.size();
     for (int i=0; i<N; i++) {
-        String8 leafName = groups.keyAt(i);
+        const String8& leafName = groups.keyAt(i);
         const sp<AaptGroup>& group = groups.valueAt(i);
 
         const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files
@@ -422,7 +422,7 @@
             set->add(leafName, group);
             resources->add(resType, set);
         } else {
-            sp<ResourceTypeSet> set = resources->valueAt(index);
+            const sp<ResourceTypeSet>& set = resources->valueAt(index);
             index = set->indexOfKey(leafName);
             if (index < 0) {
                 if (kIsDebug) {
@@ -457,7 +457,7 @@
     int N = dirs.size();
 
     for (int i=0; i<N; i++) {
-        sp<AaptDir> d = dirs.itemAt(i);
+        const sp<AaptDir>& d = dirs.itemAt(i);
         if (kIsDebug) {
             printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(),
                     d->getLeaf().string());
@@ -615,7 +615,7 @@
         // get the overlay resources of the requested type
         ssize_t index = overlayRes->indexOfKey(resTypeString);
         if (index >= 0) {
-            sp<ResourceTypeSet> overlaySet = overlayRes->valueAt(index);
+            const sp<ResourceTypeSet>& overlaySet = overlayRes->valueAt(index);
 
             // for each of the resources, check for a match in the previously built
             // non-overlay "baseset".
@@ -765,7 +765,7 @@
     return addTagAttribute(node, ns8, attr8, value, errorOnFailedInsert, false);
 }
 
-static void fullyQualifyClassName(const String8& package, sp<XMLNode> node,
+static void fullyQualifyClassName(const String8& package, const sp<XMLNode>& node,
         const String16& attrName) {
     XMLNode::attribute_entry* attr = node->editAttribute(
             String16("http://schemas.android.com/apk/res/android"), attrName);
@@ -1350,7 +1350,7 @@
             ResourceDirIterator it(resources->valueAt(index), String8("values"));
             ssize_t res;
             while ((res=it.next()) == NO_ERROR) {
-                sp<AaptFile> file = it.getFile();
+                const sp<AaptFile>& file = it.getFile();
                 res = compileResourceFile(bundle, assets, file, it.getParams(), 
                                           (current!=assets), &table);
                 if (res != NO_ERROR) {
@@ -2688,7 +2688,7 @@
         String8 dest(bundle->getRClassDir());
 
         if (bundle->getMakePackageDirs()) {
-            String8 pkg(package);
+            const String8& pkg(package);
             const char* last = pkg.string();
             const char* s = last-1;
             do {
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index d6430c0..40d5b75 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -78,7 +78,7 @@
 class StrongResourceFilter : public ResourceFilter {
 public:
     StrongResourceFilter() {}
-    StrongResourceFilter(const std::set<ConfigDescription>& configs)
+    explicit StrongResourceFilter(const std::set<ConfigDescription>& configs)
         : mConfigs(configs) {}
 
     android::status_t parse(const android::String8& str);
@@ -106,7 +106,7 @@
  */
 class InverseResourceFilter : public ResourceFilter {
 public:
-    InverseResourceFilter(const android::sp<ResourceFilter>& filter)
+    explicit InverseResourceFilter(const android::sp<ResourceFilter>& filter)
         : mFilter(filter) {}
 
     bool match(const android::ResTable_config& config) const {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 4d5bb31..76c59dd 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4081,7 +4081,7 @@
     
     j = 0;
     for (i=0; i<N; i++) {
-        sp<ConfigList> e = origOrder.itemAt(i);
+        const sp<ConfigList>& e = origOrder.itemAt(i);
         // There will always be enough room for the remaining entries.
         while (mOrderedConfigs.itemAt(j) != NULL) {
             j++;
@@ -4203,7 +4203,7 @@
 
     size_t j=0;
     for (i=0; i<N; i++) {
-        sp<Type> t = origOrder.itemAt(i);
+        const sp<Type>& t = origOrder.itemAt(i);
         // There will always be enough room for the remaining types.
         while (mOrderedTypes.itemAt(j) != NULL) {
             j++;
@@ -4636,7 +4636,7 @@
                         c->getEntries();
                 const size_t entryCount = entries.size();
                 for (size_t ei = 0; ei < entryCount; ei++) {
-                    sp<Entry> e = entries.valueAt(ei);
+                    const sp<Entry>& e = entries.valueAt(ei);
                     if (e == NULL || e->getType() != Entry::TYPE_BAG) {
                         continue;
                     }
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index 4b0d920..625b0bf 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -41,7 +41,7 @@
 public:
     struct entry {
         entry() : offset(0) { }
-        entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
+        explicit entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
         entry(const entry& o) : value(o.value), offset(o.offset),
                 hasStyles(o.hasStyles), indices(o.indices),
                 configTypeName(o.configTypeName), configs(o.configs) { }
diff --git a/tools/aapt/WorkQueue.h b/tools/aapt/WorkQueue.h
index d38f05d..ab5f969 100644
--- a/tools/aapt/WorkQueue.h
+++ b/tools/aapt/WorkQueue.h
@@ -47,7 +47,7 @@
     };
 
     /* Creates a work queue with the specified maximum number of work threads. */
-    WorkQueue(size_t maxThreads, bool canCallJava = true);
+    explicit WorkQueue(size_t maxThreads, bool canCallJava = true);
 
     /* Destroys the work queue.
      * Cancels pending work and waits for all remaining threads to complete.
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 5b215da..15ec4af 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -67,7 +67,7 @@
 static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
 static const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools");
 
-String16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, bool* outIsPublic)
+String16 getNamespaceResourcePackage(const String16& appPackage, const String16& namespaceUri, bool* outIsPublic)
 {
     //printf("%s starts with %s?\n", String8(namespaceUri).string(),
     //       String8(RESOURCES_PREFIX).string());
@@ -98,7 +98,7 @@
 
 status_t hasSubstitutionErrors(const char* fileName,
                                ResXMLTree* inXml,
-                               String16 str16)
+                               const String16& str16)
 {
     const char16_t* str = str16.string();
     const char16_t* p = str;
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 749bf9f..ac92018 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -178,7 +178,7 @@
     XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace);
     
     // Creating a CDATA node.
-    XMLNode(const String8& filename);
+    explicit XMLNode(const String8& filename);
     
     status_t collect_strings(StringPool* dest, Vector<uint32_t>* outResIds,
             bool stripComments, bool stripRawValues) const;
diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h
index 1faecd1..9bb1fd8 100644
--- a/tools/aapt/pseudolocalize.h
+++ b/tools/aapt/pseudolocalize.h
@@ -43,7 +43,7 @@
 
 class Pseudolocalizer {
  public:
-  Pseudolocalizer(PseudolocalizationMethod m);
+  explicit Pseudolocalizer(PseudolocalizationMethod m);
   ~Pseudolocalizer() { if (mImpl) delete mImpl; }
   void setMethod(PseudolocalizationMethod m);
   String16 start() { return mImpl->start(); }
diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h
index ef0d147..6858c62 100644
--- a/tools/aapt2/ConfigDescription.h
+++ b/tools/aapt2/ConfigDescription.h
@@ -51,7 +51,7 @@
     static void applyVersionForCompatibility(ConfigDescription* config);
 
     ConfigDescription();
-    ConfigDescription(const android::ResTable_config& o);
+    ConfigDescription(const android::ResTable_config& o);  // NOLINT(implicit)
     ConfigDescription(const ConfigDescription& o);
     ConfigDescription(ConfigDescription&& o);
 
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 0ba0345..09a04e0 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -100,7 +100,7 @@
     ResourceNameRef() = default;
     ResourceNameRef(const ResourceNameRef&) = default;
     ResourceNameRef(ResourceNameRef&&) = default;
-    ResourceNameRef(const ResourceName& rhs);
+    ResourceNameRef(const ResourceName& rhs);  // NOLINT(implicit)
     ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e);
     ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
     ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
@@ -126,7 +126,7 @@
 
     ResourceId();
     ResourceId(const ResourceId& rhs);
-    ResourceId(uint32_t resId);
+    ResourceId(uint32_t resId);  // NOLINT(implicit)
     ResourceId(uint8_t p, uint8_t t, uint16_t e);
 
     bool isValid() const;
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 4d418d9..460de0e 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -274,7 +274,7 @@
 }
 
 bool ResourceTable::addResource(const ResourceNameRef& name,
-                                const ResourceId resId,
+                                const ResourceId& resId,
                                 const ConfigDescription& config,
                                 const StringPiece& product,
                                 std::unique_ptr<Value> value,
@@ -325,7 +325,7 @@
 }
 
 bool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name,
-                                            const ResourceId id,
+                                            const ResourceId& id,
                                             const ConfigDescription& config,
                                             const StringPiece& product,
                                             std::unique_ptr<Value> value,
@@ -335,12 +335,12 @@
 }
 
 bool ResourceTable::addResourceImpl(const ResourceNameRef& name,
-                                    const ResourceId resId,
+                                    const ResourceId& resId,
                                     const ConfigDescription& config,
                                     const StringPiece& product,
                                     std::unique_ptr<Value> value,
                                     const char* validChars,
-                                    std::function<int(Value*,Value*)> conflictResolver,
+                                    const std::function<int(Value*,Value*)>& conflictResolver,
                                     IDiagnostics* diag) {
     assert(value && "value can't be nullptr");
     assert(diag && "diagnostics can't be nullptr");
@@ -426,18 +426,18 @@
     return true;
 }
 
-bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId resId,
+bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId& resId,
                                    const Symbol& symbol, IDiagnostics* diag) {
     return setSymbolStateImpl(name, resId, symbol, kValidNameChars, diag);
 }
 
 bool ResourceTable::setSymbolStateAllowMangled(const ResourceNameRef& name,
-                                               const ResourceId resId,
+                                               const ResourceId& resId,
                                                const Symbol& symbol, IDiagnostics* diag) {
     return setSymbolStateImpl(name, resId, symbol, kValidNameMangledChars, diag);
 }
 
-bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId resId,
+bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId& resId,
                                        const Symbol& symbol, const char* validChars,
                                        IDiagnostics* diag) {
     assert(diag && "diagnostics can't be nullptr");
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index a5efe35..6b52a43 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -103,7 +103,7 @@
      */
     std::vector<std::unique_ptr<ResourceConfigValue>> values;
 
-    ResourceEntry(const StringPiece& name) : name(name.toString()) { }
+    explicit ResourceEntry(const StringPiece& name) : name(name.toString()) { }
 
     ResourceConfigValue* findValue(const ConfigDescription& config);
     ResourceConfigValue* findValue(const ConfigDescription& config, const StringPiece& product);
@@ -200,7 +200,7 @@
                      IDiagnostics* diag);
 
     bool addResource(const ResourceNameRef& name,
-                     const ResourceId resId,
+                     const ResourceId& resId,
                      const ConfigDescription& config,
                      const StringPiece& product,
                      std::unique_ptr<Value> value,
@@ -231,19 +231,19 @@
                                  IDiagnostics* diag);
 
     bool addResourceAllowMangled(const ResourceNameRef& name,
-                                 const ResourceId id,
+                                 const ResourceId& id,
                                  const ConfigDescription& config,
                                  const StringPiece& product,
                                  std::unique_ptr<Value> value,
                                  IDiagnostics* diag);
 
     bool setSymbolState(const ResourceNameRef& name,
-                        const ResourceId resId,
+                        const ResourceId& resId,
                         const Symbol& symbol,
                         IDiagnostics* diag);
 
     bool setSymbolStateAllowMangled(const ResourceNameRef& name,
-                                    const ResourceId resId,
+                                    const ResourceId& resId,
                                     const Symbol& symbol,
                                     IDiagnostics* diag);
 
@@ -294,16 +294,16 @@
                               IDiagnostics* diag);
 
     bool addResourceImpl(const ResourceNameRef& name,
-                         ResourceId resId,
+                         const ResourceId& resId,
                          const ConfigDescription& config,
                          const StringPiece& product,
                          std::unique_ptr<Value> value,
                          const char* validChars,
-                         std::function<int(Value*,Value*)> conflictResolver,
+                         const std::function<int(Value*,Value*)>& conflictResolver,
                          IDiagnostics* diag);
 
     bool setSymbolStateImpl(const ResourceNameRef& name,
-                            ResourceId resId,
+                            const ResourceId& resId,
                             const Symbol& symbol,
                             const char* validChars,
                             IDiagnostics* diag);
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 7dc88ded..773616d 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -545,7 +545,7 @@
 std::unique_ptr<Item> parseItemForAttribute(
         const StringPiece& value,
         uint32_t typeMask,
-        std::function<void(const ResourceName&)> onCreateReference) {
+        const std::function<void(const ResourceName&)>& onCreateReference) {
     std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value);
     if (nullOrEmpty) {
         return std::move(nullOrEmpty);
@@ -604,7 +604,7 @@
  */
 std::unique_ptr<Item> parseItemForAttribute(
         const StringPiece& str, const Attribute* attr,
-        std::function<void(const ResourceName&)> onCreateReference) {
+        const std::function<void(const ResourceName&)>& onCreateReference) {
     const uint32_t typeMask = attr->typeMask;
     std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference);
     if (value) {
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 31b8e89..a57d89d 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -163,11 +163,11 @@
  */
 std::unique_ptr<Item> parseItemForAttribute(
         const StringPiece& value, const Attribute* attr,
-        std::function<void(const ResourceName&)> onCreateReference = {});
+        const std::function<void(const ResourceName&)>& onCreateReference = {});
 
 std::unique_ptr<Item> parseItemForAttribute(
         const StringPiece& value, uint32_t typeMask,
-        std::function<void(const ResourceName&)> onCreateReference = {});
+        const std::function<void(const ResourceName&)>& onCreateReference = {});
 
 uint32_t androidTypeToAttributeTypeMask(uint16_t type);
 
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 8ae71ad..e6af716 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -198,7 +198,7 @@
 struct RawString : public BaseItem<RawString> {
     StringPool::Ref value;
 
-    RawString(const StringPool::Ref& ref);
+    explicit RawString(const StringPool::Ref& ref);
 
     bool equals(const Value* value) const override;
     bool flatten(android::Res_value* outValue) const override;
@@ -209,7 +209,7 @@
 struct String : public BaseItem<String> {
     StringPool::Ref value;
 
-    String(const StringPool::Ref& ref);
+    explicit String(const StringPool::Ref& ref);
 
     bool equals(const Value* value) const override;
     bool flatten(android::Res_value* outValue) const override;
@@ -220,7 +220,7 @@
 struct StyledString : public BaseItem<StyledString> {
     StringPool::StyleRef value;
 
-    StyledString(const StringPool::StyleRef& ref);
+    explicit StyledString(const StringPool::StyleRef& ref);
 
     bool equals(const Value* value) const override;
     bool flatten(android::Res_value* outValue) const override;
@@ -237,7 +237,7 @@
     io::IFile* file = nullptr;
 
     FileReference() = default;
-    FileReference(const StringPool::Ref& path);
+    explicit FileReference(const StringPool::Ref& path);
 
     bool equals(const Value* value) const override;
     bool flatten(android::Res_value* outValue) const override;
@@ -252,7 +252,7 @@
     android::Res_value value;
 
     BinaryPrimitive() = default;
-    BinaryPrimitive(const android::Res_value& val);
+    explicit BinaryPrimitive(const android::Res_value& val);
     BinaryPrimitive(uint8_t dataType, uint32_t data);
 
     bool equals(const Value* value) const override;
@@ -272,7 +272,7 @@
     int32_t maxInt;
     std::vector<Symbol> symbols;
 
-    Attribute(bool w, uint32_t t = 0u);
+    explicit Attribute(bool w, uint32_t t = 0u);
 
     bool equals(const Value* value) const override;
     Attribute* clone(StringPool* newPool) const override;
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 91e755d..ccf0383 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -52,7 +52,7 @@
     return p.first < entryId;
 }
 
-size_t findAttributeSdkLevel(ResourceId id) {
+size_t findAttributeSdkLevel(const ResourceId& id) {
     if (id.packageId() != 0x01 && id.typeId() != 0x01) {
         return 0;
     }
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index f28679f..c9dbdca 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -47,7 +47,7 @@
     SDK_MARSHMALLOW = 23,
 };
 
-size_t findAttributeSdkLevel(ResourceId id);
+size_t findAttributeSdkLevel(const ResourceId& id);
 size_t findAttributeSdkLevel(const ResourceName& name);
 std::pair<StringPiece, int> getDevelopmentSdkCodeNameAndVersion();
 
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 72ae9d1..13545be 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -65,7 +65,7 @@
     private:
         friend class StringPool;
 
-        Ref(Entry* entry);
+        explicit Ref(Entry* entry);
 
         Entry* mEntry;
     };
@@ -88,7 +88,7 @@
     private:
         friend class StringPool;
 
-        StyleRef(StyleEntry* entry);
+        explicit StyleRef(StyleEntry* entry);
 
         StyleEntry* mEntry;
     };
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index 501ae9d..4a3f1e1 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -28,7 +28,7 @@
  * Assigns the intended ID to the ResourceTablePackage, ResourceTableType, and ResourceEntry,
  * as long as there is no existing ID or the ID is the same.
  */
-static bool assignId(IDiagnostics* diag, const ResourceId id, const ResourceName& name,
+static bool assignId(IDiagnostics* diag, const ResourceId& id, const ResourceName& name,
                      ResourceTablePackage* pkg, ResourceTableType* type, ResourceEntry* entry) {
     if (pkg->id.value() == id.packageId()) {
         if (!type->id || type->id.value() == id.typeId()) {
diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp
index 0b92ba5..b25bfa7 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -64,7 +64,7 @@
 
     ::testing::AssertionResult exists(ResTable* table,
                                       const StringPiece& expectedName,
-                                      const ResourceId expectedId,
+                                      const ResourceId& expectedId,
                                       const ConfigDescription& expectedConfig,
                                       const uint8_t expectedDataType, const uint32_t expectedData,
                                       const uint32_t expectedSpecFlags) {
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index d26f2e4..4d1e178 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -43,7 +43,7 @@
     }
 
     ::testing::AssertionResult flatten(xml::XmlResource* doc, android::ResXMLTree* outTree,
-                                       XmlFlattenerOptions options = {}) {
+                                       const XmlFlattenerOptions& options = {}) {
         using namespace android; // For NO_ERROR on windows because it is a macro.
 
         BigBuffer buffer(1024);
diff --git a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
index b6d8f2d..1156b01 100644
--- a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
+++ b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
@@ -14,4 +14,7 @@
      limitations under the License.
 -->
 
-<manifest package="com.android.aapt.app.one" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.aapt.app.one" coreApp="true">
+    <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 45472ff..ff777a3 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -528,7 +528,7 @@
 
 static bool writeStableIdMapToPath(IDiagnostics* diag,
                                    const std::unordered_map<ResourceName, ResourceId>& idMap,
-                                   const std::string idMapPath) {
+                                   const std::string& idMapPath) {
     std::ofstream fout(idMapPath, std::ofstream::binary);
     if (!fout) {
         diag->error(DiagMessage(idMapPath) << strerror(errno));
@@ -823,7 +823,7 @@
     }
 
     bool writeJavaFile(ResourceTable* table, const StringPiece& packageNameToGenerate,
-                       const StringPiece& outPackage, JavaClassGeneratorOptions javaOptions) {
+                       const StringPiece& outPackage, const JavaClassGeneratorOptions& javaOptions) {
         if (!mOptions.generateJavaClassPath) {
             return true;
         }
@@ -1191,6 +1191,12 @@
                                                                      mContext->getDiagnostics())) {
             AppInfo& appInfo = maybeAppInfo.value();
             mContext->setCompilationPackage(appInfo.package);
+            if (appInfo.minSdkVersion) {
+                if (Maybe<int> maybeMinSdkVersion =
+                        ResourceUtils::tryParseSdkVersion(appInfo.minSdkVersion.value())) {
+                    mContext->setMinSdkVersion(maybeMinSdkVersion.value());
+                }
+            }
         } else {
             return 1;
         }
@@ -1393,32 +1399,6 @@
             return 1;
         }
 
-        // Must come before ResourceFileFlattener as ResourceFileFlattener
-        // relies on the minSdkVersion to properly flatten files.
-        Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get(),
-                                                                 mContext->getDiagnostics());
-        if (maybeAppInfo && maybeAppInfo.value().minSdkVersion) {
-            if (Maybe<int> maybeMinSdkVersion =
-                    ResourceUtils::tryParseSdkVersion(maybeAppInfo.value().minSdkVersion.value())) {
-                mContext->setMinSdkVersion(maybeMinSdkVersion.value());
-            }
-        }
-
-        ResourceFileFlattenerOptions fileFlattenerOptions;
-        fileFlattenerOptions.keepRawValues = mOptions.staticLib;
-        fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
-        fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
-        fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
-        fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
-        fileFlattenerOptions.updateProguardSpec =
-                static_cast<bool>(mOptions.generateProguardRulesPath);
-        ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);
-
-        if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
-            return 1;
-        }
-
         if (!mOptions.noAutoVersion) {
             AutoVersioner versioner;
             if (!versioner.consume(mContext, &mFinalTable)) {
@@ -1440,6 +1420,23 @@
             }
         }
 
+        // Write out the table to an archive. Optimizations to the table should come before this
+        // step.
+        ResourceFileFlattenerOptions fileFlattenerOptions;
+        fileFlattenerOptions.keepRawValues = mOptions.staticLib;
+        fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
+        fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
+        fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
+        fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
+        fileFlattenerOptions.updateProguardSpec =
+                static_cast<bool>(mOptions.generateProguardRulesPath);
+        ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);
+
+        if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
+            mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
+            return 1;
+        }
+
         if (mOptions.staticLib) {
             if (!flattenTableToPb(&mFinalTable, archiveWriter.get())) {
                 mContext->getDiagnostics()->error(DiagMessage()
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 1203db7..e7edcc5 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -81,6 +81,22 @@
     return true;
 }
 
+/**
+ * The coreApp attribute in <manifest> is not a regular AAPT attribute, so type checking on it
+ * is manual.
+ */
+static bool fixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) {
+    if (xml::Attribute* attr = el->findAttribute("", "coreApp")) {
+        std::unique_ptr<BinaryPrimitive> result = ResourceUtils::tryParseBool(attr->value);
+        if (!result) {
+            diag->error(DiagMessage(el->lineNumber) << "attribute coreApp must be a boolean");
+            return false;
+        }
+        attr->compiledValue = std::move(result);
+    }
+    return true;
+}
+
 bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag) {
     // First verify some options.
     if (mOptions.renameManifestPackage) {
@@ -111,6 +127,7 @@
     // Manifest actions.
     xml::XmlNodeAction& manifestAction = (*executor)["manifest"];
     manifestAction.action(verifyManifest);
+    manifestAction.action(fixCoreAppAttribute);
     manifestAction.action([&](xml::Element* el) -> bool {
         if (mOptions.versionNameDefault) {
             if (el->findAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 1c69a8c..16ab9ab 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -253,4 +253,24 @@
     EXPECT_EQ(std::string("0x10000000"), attr->value);
 }
 
+TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
+    EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"hello\" />"));
+    EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"1dp\" />"));
+
+    std::unique_ptr<xml::XmlResource> doc =
+            verify("<manifest package=\"android\" coreApp=\"true\" />");
+    ASSERT_NE(nullptr, doc);
+
+    xml::Element* el = xml::findRootElement(doc.get());
+    ASSERT_NE(nullptr, el);
+
+    EXPECT_EQ("manifest", el->name);
+
+    xml::Attribute* attr = el->findAttribute("", "coreApp");
+    ASSERT_NE(nullptr, attr);
+
+    EXPECT_NE(nullptr, attr->compiledValue);
+    EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(attr->compiledValue.get()));
+}
+
 } // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 2cd2639..379c991 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -135,14 +135,14 @@
                           const bool manglePackage,
                           const bool overlay,
                           const bool allowNewResources,
-                          FileMergeCallback callback) {
+                          const FileMergeCallback& callback) {
     bool error = false;
 
     for (auto& srcType : srcPackage->types) {
         ResourceTableType* dstType = mMasterPackage->findOrCreateType(srcType->type);
         if (srcType->symbolStatus.state == SymbolState::kPublic) {
             if (dstType->symbolStatus.state == SymbolState::kPublic && dstType->id && srcType->id
-                    && dstType->id.value() == srcType->id.value()) {
+                    && dstType->id.value() != srcType->id.value()) {
                 // Both types are public and have different IDs.
                 mContext->getDiagnostics()->error(DiagMessage(src)
                                                   << "can not merge type '"
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index 6997f93..3473a27 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -115,7 +115,7 @@
                  const bool manglePackage,
                  const bool overlay,
                  const bool allowNewResources,
-                 FileMergeCallback callback);
+                 const FileMergeCallback& callback);
 
     std::unique_ptr<FileReference> cloneAndMangleFile(const std::string& package,
                                                       const FileReference& value);
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 300b56d..ff3e21f 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -164,6 +164,63 @@
     EXPECT_EQ(0x0u, foo->value.data);
 }
 
+TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
+    std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
+            .setPackageId("", 0x7f)
+            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+            .build();
+    std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
+            .setPackageId("", 0x7f)
+            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+            .build();
+
+    ResourceTable finalTable;
+    TableMergerOptions tableMergerOptions;
+    tableMergerOptions.autoAddOverlay = false;
+    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+
+    ASSERT_TRUE(merger.merge({}, base.get()));
+    ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
+}
+
+TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
+    std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
+            .setPackageId("", 0x7f)
+            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+            .build();
+    std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
+            .setPackageId("", 0x7f)
+            .setSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), SymbolState::kPublic)
+            .build();
+
+    ResourceTable finalTable;
+    TableMergerOptions tableMergerOptions;
+    tableMergerOptions.autoAddOverlay = false;
+    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+
+    ASSERT_TRUE(merger.merge({}, base.get()));
+    ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
+}
+
+TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
+    std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
+            .setPackageId("", 0x7f)
+            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
+            .build();
+    std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
+            .setPackageId("", 0x7f)
+            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), SymbolState::kPublic)
+            .build();
+
+    ResourceTable finalTable;
+    TableMergerOptions tableMergerOptions;
+    tableMergerOptions.autoAddOverlay = false;
+    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+
+    ASSERT_TRUE(merger.merge({}, base.get()));
+    ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
+}
+
 TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
     std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
             .setPackageId("", 0x7f)
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 02af5e3..a29d8dc 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -126,8 +126,9 @@
                     mError = true;
 
                 }
-            } else {
-                // We still encode references.
+            } else if (!attr.compiledValue) {
+                // We still encode references, but only if we haven't manually set this to
+                // another compiled value.
                 attr.compiledValue = ResourceUtils::tryParseReference(attr.value);
             }
 
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 6c506df..0c92718 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -63,7 +63,7 @@
     return nullptr;
 }
 
-const SymbolTable::Symbol* SymbolTable::findById(ResourceId id) {
+const SymbolTable::Symbol* SymbolTable::findById(const ResourceId& id) {
     if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) {
         return s.get();
     }
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 43f4dd7..bd01b64 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -86,7 +86,7 @@
      * are typically stored in a cache which may evict entries.
      */
     const Symbol* findByName(const ResourceName& name);
-    const Symbol* findById(ResourceId id);
+    const Symbol* findById(const ResourceId& id);
 
     /**
      * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 98ff87f..ca25c6a 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -228,7 +228,7 @@
             }
 
         } else if (pbValue.has_compound_value()) {
-            const pb::CompoundValue pbCompoundValue = pbValue.compound_value();
+            const pb::CompoundValue& pbCompoundValue = pbValue.compound_value();
             if (pbCompoundValue.has_attr()) {
                 const pb::Attribute& pbAttr = pbCompoundValue.attr();
                 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 3674f0f..b62ffac 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -89,7 +89,7 @@
 
     WifiInfo getConnectionInfo();
 
-    boolean setWifiEnabled(boolean enable);
+    boolean setWifiEnabled(String packageName, boolean enable);
 
     int getWifiEnabledState();
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6cf1921..b134cf7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -19,6 +19,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.DhcpInfo;
@@ -561,6 +562,28 @@
     public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
 
     /**
+     * Activity Action: Show UI to get user approval to enable WiFi.
+     * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
+     *           the name of the app requesting the action.
+     * <p>Output: Nothing.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE";
+
+    /**
+     * Activity Action: Show UI to get user approval to disable WiFi.
+     * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
+     *           the name of the app requesting the action.
+     * <p>Output: Nothing.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE";
+
+    /**
      * Internally used Wi-Fi lock mode representing the case were no locks are held.
      * @hide
      */
@@ -1443,7 +1466,7 @@
      */
     public boolean setWifiEnabled(boolean enabled) {
         try {
-            return mService.setWifiEnabled(enabled);
+            return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }