Merge changes from topic "downloadvuln"

* changes:
  Execute "strict" queries with extra parentheses.
  Add support for appending standalone phrases.
diff --git a/Android.bp b/Android.bp
index 694bf26..8c81534 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1185,6 +1185,7 @@
         "core/java/overview.html",
         ":current-support-api",
     ],
+    dex_api_filename: "public-dex.txt",
     private_dex_api_filename: "private-dex.txt",
     removed_dex_api_filename: "removed-dex.txt",
     args: framework_docs_args +
diff --git a/Android.mk b/Android.mk
index 031809c..7890983 100644
--- a/Android.mk
+++ b/Android.mk
@@ -712,6 +712,7 @@
 LOCAL_SRC_GREYLIST := frameworks/base/config/hiddenapi-light-greylist.txt
 LOCAL_SRC_VENDOR_LIST := frameworks/base/config/hiddenapi-vendor-list.txt
 LOCAL_SRC_FORCE_BLACKLIST := frameworks/base/config/hiddenapi-force-blacklist.txt
+LOCAL_SRC_PUBLIC_API := $(INTERNAL_PLATFORM_DEX_API_FILE)
 LOCAL_SRC_PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
 LOCAL_SRC_REMOVED_API := $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)
 
@@ -719,6 +720,7 @@
 	$(LOCAL_SRC_GREYLIST) \
 	$(LOCAL_SRC_VENDOR_LIST) \
 	$(LOCAL_SRC_FORCE_BLACKLIST) \
+	$(LOCAL_SRC_PUBLIC_API) \
 	$(LOCAL_SRC_PRIVATE_API) \
 	$(LOCAL_SRC_REMOVED_API)
 
@@ -791,7 +793,8 @@
 #   (4) subtract entries shared with LOCAL_LIGHT_GREYLIST
 $(LOCAL_DARK_GREYLIST): $(LOCAL_SRC_ALL) $(LOCAL_LIGHT_GREYLIST)
 	comm -13 <(sort $(LOCAL_LIGHT_GREYLIST) $(LOCAL_SRC_FORCE_BLACKLIST)) \
-	         <(sed 's/\->.*//' $(LOCAL_LIGHT_GREYLIST) | sed 's/\(.*\/\).*/\1/' | sort | uniq | \
+	         <(cat $(LOCAL_SRC_PUBLIC_API) $(LOCAL_LIGHT_GREYLIST) | \
+	               sed 's/\->.*//' | sed 's/\(.*\/\).*/\1/' | sort | uniq | \
 	               while read PKG_NAME; do \
 	                   grep -E "^$${PKG_NAME}[^/;]*;" $(LOCAL_SRC_PRIVATE_API); \
 	               done | sort | uniq) \
diff --git a/api/system-current.txt b/api/system-current.txt
index 7c0d958..924d3af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5180,8 +5180,8 @@
     method public int[] getAvailableServices();
     method public android.telephony.CellIdentity getCellIdentity();
     method public int getDomain();
-    method public int getReasonForDenial();
     method public int getRegState();
+    method public int getRejectCause();
     method public int getTransportType();
     method public boolean isEmergencyEnabled();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 89b1f41..6984aa2 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -33,7 +33,7 @@
 namespace statsd {
 
 struct GaugeAtom {
-    GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs, int wallClockNs)
+    GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs, int64_t wallClockNs)
         : mFields(fields), mElapsedTimestamps(elapsedTimeNs), mWallClockTimestampNs(wallClockNs) {
     }
     std::shared_ptr<vector<FieldValue>> mFields;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f27b286..3f579bc 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3080,16 +3080,32 @@
          */
         public int processState;
 
+        /**
+         * Whether the app is focused in multi-window environment.
+         * @hide
+         */
+        public boolean isFocused;
+
+        /**
+         * Copy of {@link com.android.server.am.ProcessRecord#lastActivityTime} of the process.
+         * @hide
+         */
+        public long lastActivityTime;
+
         public RunningAppProcessInfo() {
             importance = IMPORTANCE_FOREGROUND;
             importanceReasonCode = REASON_UNKNOWN;
             processState = PROCESS_STATE_IMPORTANT_FOREGROUND;
+            isFocused = false;
+            lastActivityTime = 0;
         }
 
         public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
             processName = pProcessName;
             pid = pPid;
             pkgList = pArr;
+            isFocused = false;
+            lastActivityTime = 0;
         }
 
         public int describeContents() {
@@ -3110,6 +3126,8 @@
             ComponentName.writeToParcel(importanceReasonComponent, dest);
             dest.writeInt(importanceReasonImportance);
             dest.writeInt(processState);
+            dest.writeInt(isFocused ? 1 : 0);
+            dest.writeLong(lastActivityTime);
         }
 
         public void readFromParcel(Parcel source) {
@@ -3126,6 +3144,8 @@
             importanceReasonComponent = ComponentName.readFromParcel(source);
             importanceReasonImportance = source.readInt();
             processState = source.readInt();
+            isFocused = source.readInt() != 0;
+            lastActivityTime = source.readLong();
         }
 
         public static final Creator<RunningAppProcessInfo> CREATOR =
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index cba7003..3dbc312 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -128,7 +128,7 @@
             in boolean stopProfiling);
     void activityResumed(in IBinder token);
     void activityPaused(in IBinder token);
-    oneway void activityStopped(in IBinder token, in Bundle state,
+    void activityStopped(in IBinder token, in Bundle state,
             in PersistableBundle persistentState, in CharSequence description);
     oneway void activityDestroyed(in IBinder token);
     void activityRelaunched(in IBinder token);
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ab2cf86..175b405 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -21,9 +21,7 @@
 import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.Slog;
-import android.util.SparseIntArray;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.util.FastPrintWriter;
@@ -36,12 +34,7 @@
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * Base class for a remotable object, the core part of a lightweight
@@ -783,442 +776,3 @@
     }
 }
 
-/**
- * Java proxy for a native IBinder object.
- * Allocated and constructed by the native javaObjectforIBinder function. Never allocated
- * directly from Java code.
- */
-final class BinderProxy implements IBinder {
-    // See android_util_Binder.cpp for the native half of this.
-
-    // Assume the process-wide default value when created
-    volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
-
-    /*
-     * Map from longs to BinderProxy, retaining only a WeakReference to the BinderProxies.
-     * We roll our own only because we need to lazily remove WeakReferences during accesses
-     * to avoid accumulating junk WeakReference objects. WeakHashMap isn't easily usable
-     * because we want weak values, not keys.
-     * Our hash table is never resized, but the number of entries is unlimited;
-     * performance degrades as occupancy increases significantly past MAIN_INDEX_SIZE.
-     * Not thread-safe. Client ensures there's a single access at a time.
-     */
-    private static final class ProxyMap {
-        private static final int LOG_MAIN_INDEX_SIZE = 8;
-        private static final int MAIN_INDEX_SIZE = 1 <<  LOG_MAIN_INDEX_SIZE;
-        private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1;
-        // Debuggable builds will throw an AssertionError if the number of map entries exceeds:
-        private static final int CRASH_AT_SIZE = 20_000;
-
-        /**
-         * We next warn when we exceed this bucket size.
-         */
-        private int mWarnBucketSize = 20;
-
-        /**
-         * Increment mWarnBucketSize by WARN_INCREMENT each time we warn.
-         */
-        private static final int WARN_INCREMENT = 10;
-
-        /**
-         * Hash function tailored to native pointers.
-         * Returns a value < MAIN_INDEX_SIZE.
-         */
-        private static int hash(long arg) {
-            return ((int) ((arg >> 2) ^ (arg >> (2 + LOG_MAIN_INDEX_SIZE)))) & MAIN_INDEX_MASK;
-        }
-
-        /**
-         * Return the total number of pairs in the map.
-         */
-        private int size() {
-            int size = 0;
-            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
-                if (a != null) {
-                    size += a.size();
-                }
-            }
-            return size;
-        }
-
-        /**
-         * Return the total number of pairs in the map containing values that have
-         * not been cleared. More expensive than the above size function.
-         */
-        private int unclearedSize() {
-            int size = 0;
-            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
-                if (a != null) {
-                    for (WeakReference<BinderProxy> ref : a) {
-                        if (ref.get() != null) {
-                            ++size;
-                        }
-                    }
-                }
-            }
-            return size;
-        }
-
-        /**
-         * Remove ith entry from the hash bucket indicated by hash.
-         */
-        private void remove(int hash, int index) {
-            Long[] keyArray = mMainIndexKeys[hash];
-            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[hash];
-            int size = valueArray.size();  // KeyArray may have extra elements.
-            // Move last entry into empty slot, and truncate at end.
-            if (index != size - 1) {
-                keyArray[index] = keyArray[size - 1];
-                valueArray.set(index, valueArray.get(size - 1));
-            }
-            valueArray.remove(size - 1);
-            // Just leave key array entry; it's unused. We only trust the valueArray size.
-        }
-
-        /**
-         * Look up the supplied key. If we have a non-cleared entry for it, return it.
-         */
-        BinderProxy get(long key) {
-            int myHash = hash(key);
-            Long[] keyArray = mMainIndexKeys[myHash];
-            if (keyArray == null) {
-                return null;
-            }
-            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
-            int bucketSize = valueArray.size();
-            for (int i = 0; i < bucketSize; ++i) {
-                long foundKey = keyArray[i];
-                if (key == foundKey) {
-                    WeakReference<BinderProxy> wr = valueArray.get(i);
-                    BinderProxy bp = wr.get();
-                    if (bp != null) {
-                        return bp;
-                    } else {
-                        remove(myHash, i);
-                        return null;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private int mRandom;  // A counter used to generate a "random" index. World's 2nd worst RNG.
-
-        /**
-         * Add the key-value pair to the map.
-         * Requires that the indicated key is not already in the map.
-         */
-        void set(long key, @NonNull BinderProxy value) {
-            int myHash = hash(key);
-            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
-            if (valueArray == null) {
-                valueArray = mMainIndexValues[myHash] = new ArrayList<>();
-                mMainIndexKeys[myHash] = new Long[1];
-            }
-            int size = valueArray.size();
-            WeakReference<BinderProxy> newWr = new WeakReference<>(value);
-            // First look for a cleared reference.
-            // This ensures that ArrayList size is bounded by the maximum occupancy of
-            // that bucket.
-            for (int i = 0; i < size; ++i) {
-                if (valueArray.get(i).get() == null) {
-                    valueArray.set(i, newWr);
-                    Long[] keyArray = mMainIndexKeys[myHash];
-                    keyArray[i] = key;
-                    if (i < size - 1) {
-                        // "Randomly" check one of the remaining entries in [i+1, size), so that
-                        // needlessly long buckets are eventually pruned.
-                        int rnd = Math.floorMod(++mRandom, size - (i + 1));
-                        if (valueArray.get(i + 1 + rnd).get() == null) {
-                            remove(myHash, i + 1 + rnd);
-                        }
-                    }
-                    return;
-                }
-            }
-            valueArray.add(size, newWr);
-            Long[] keyArray = mMainIndexKeys[myHash];
-            if (keyArray.length == size) {
-                // size >= 1, since we initially allocated one element
-                Long[] newArray = new Long[size + size / 2 + 2];
-                System.arraycopy(keyArray, 0, newArray, 0, size);
-                newArray[size] = key;
-                mMainIndexKeys[myHash] = newArray;
-            } else {
-                keyArray[size] = key;
-            }
-            if (size >= mWarnBucketSize) {
-                final int totalSize = size();
-                Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
-                        + " total = " + totalSize);
-                mWarnBucketSize += WARN_INCREMENT;
-                if (Build.IS_DEBUGGABLE && totalSize >= CRASH_AT_SIZE) {
-                    // Use the number of uncleared entries to determine whether we should
-                    // really report a histogram and crash. We don't want to fundamentally
-                    // change behavior for a debuggable process, so we GC only if we are
-                    // about to crash.
-                    final int totalUnclearedSize = unclearedSize();
-                    if (totalUnclearedSize >= CRASH_AT_SIZE) {
-                        dumpProxyInterfaceCounts();
-                        dumpPerUidProxyCounts();
-                        Runtime.getRuntime().gc();
-                        throw new AssertionError("Binder ProxyMap has too many entries: "
-                                + totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
-                                + unclearedSize() + " (uncleared after GC). BinderProxy leak?");
-                    } else if (totalSize > 3 * totalUnclearedSize / 2) {
-                        Log.v(Binder.TAG, "BinderProxy map has many cleared entries: "
-                                + (totalSize - totalUnclearedSize) + " of " + totalSize
-                                + " are cleared");
-                    }
-                }
-            }
-        }
-
-        /**
-         * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
-         */
-        private void dumpProxyInterfaceCounts() {
-            Map<String, Integer> counts = new HashMap<>();
-            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
-                if (a != null) {
-                    for (WeakReference<BinderProxy> weakRef : a) {
-                        BinderProxy bp = weakRef.get();
-                        String key;
-                        if (bp == null) {
-                            key = "<cleared weak-ref>";
-                        } else {
-                            try {
-                                key = bp.getInterfaceDescriptor();
-                            } catch (Throwable t) {
-                                key = "<exception during getDescriptor>";
-                            }
-                        }
-                        Integer i = counts.get(key);
-                        if (i == null) {
-                            counts.put(key, 1);
-                        } else {
-                            counts.put(key, i + 1);
-                        }
-                    }
-                }
-            }
-            Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
-                    new Map.Entry[counts.size()]);
-            Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b)
-                    -> b.getValue().compareTo(a.getValue()));
-            Log.v(Binder.TAG, "BinderProxy descriptor histogram (top ten):");
-            int printLength = Math.min(10, sorted.length);
-            for (int i = 0; i < printLength; i++) {
-                Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x"
-                        + sorted[i].getValue());
-            }
-        }
-
-        /**
-         * Dump per uid binder proxy counts to the logcat.
-         */
-        private void dumpPerUidProxyCounts() {
-            SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
-            if (counts.size() == 0) return;
-            Log.d(Binder.TAG, "Per Uid Binder Proxy Counts:");
-            for (int i = 0; i < counts.size(); i++) {
-                final int uid = counts.keyAt(i);
-                final int binderCount = counts.valueAt(i);
-                Log.d(Binder.TAG, "UID : " + uid + "  count = " + binderCount);
-            }
-        }
-
-        // Corresponding ArrayLists in the following two arrays always have the same size.
-        // They contain no empty entries. However WeakReferences in the values ArrayLists
-        // may have been cleared.
-
-        // mMainIndexKeys[i][j] corresponds to mMainIndexValues[i].get(j) .
-        // The values ArrayList has the proper size(), the corresponding keys array
-        // is always at least the same size, but may be larger.
-        // If either a particular keys array, or the corresponding values ArrayList
-        // are null, then they both are.
-        private final Long[][] mMainIndexKeys = new Long[MAIN_INDEX_SIZE][];
-        private final ArrayList<WeakReference<BinderProxy>>[] mMainIndexValues =
-                new ArrayList[MAIN_INDEX_SIZE];
-    }
-
-    @GuardedBy("sProxyMap")
-    private static final ProxyMap sProxyMap = new ProxyMap();
-
-    /**
-      * Dump proxy debug information.
-      *
-      * @hide
-      */
-    private static void dumpProxyDebugInfo() {
-        if (Build.IS_DEBUGGABLE) {
-            synchronized (sProxyMap) {
-                sProxyMap.dumpProxyInterfaceCounts();
-            }
-            // Note that we don't call dumpPerUidProxyCounts(); this is because this
-            // method may be called as part of the uid limit being hit, and calling
-            // back into the UID tracking code would cause us to try to acquire a mutex
-            // that is held during that callback.
-        }
-    }
-
-    /**
-     * Return a BinderProxy for IBinder.
-     * If we previously returned a BinderProxy bp for the same iBinder, and bp is still
-     * in use, then we return the same bp.
-     *
-     * @param nativeData C++ pointer to (possibly still empty) BinderProxyNativeData.
-     * Takes ownership of nativeData iff <result>.mNativeData == nativeData, or if
-     * we exit via an exception.  If neither applies, it's the callers responsibility to
-     * recycle nativeData.
-     * @param iBinder C++ pointer to IBinder. Does not take ownership of referenced object.
-     */
-    private static BinderProxy getInstance(long nativeData, long iBinder) {
-        BinderProxy result;
-        synchronized (sProxyMap) {
-            try {
-                result = sProxyMap.get(iBinder);
-                if (result != null) {
-                    return result;
-                }
-                result = new BinderProxy(nativeData);
-            } catch (Throwable e) {
-                // We're throwing an exception (probably OOME); don't drop nativeData.
-                NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
-                        nativeData);
-                throw e;
-            }
-            NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
-            // The registry now owns nativeData, even if registration threw an exception.
-            sProxyMap.set(iBinder, result);
-        }
-        return result;
-    }
-
-    private BinderProxy(long nativeData) {
-        mNativeData = nativeData;
-    }
-
-    /**
-     * Guestimate of native memory associated with a BinderProxy.
-     * This includes the underlying IBinder, associated DeathRecipientList, and KeyedVector
-     * that points back to us. We guess high since it includes a GlobalRef, which
-     * may be in short supply.
-     */
-    private static final int NATIVE_ALLOCATION_SIZE = 1000;
-
-    // Use a Holder to allow static initialization of BinderProxy in the boot image, and
-    // to avoid some initialization ordering issues.
-    private static class NoImagePreloadHolder {
-        public static final long sNativeFinalizer = getNativeFinalizer();
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                BinderProxy.class.getClassLoader(), sNativeFinalizer, NATIVE_ALLOCATION_SIZE);
-    }
-
-    public native boolean pingBinder();
-    public native boolean isBinderAlive();
-
-    public IInterface queryLocalInterface(String descriptor) {
-        return null;
-    }
-
-    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
-        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
-
-        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
-            // For now, avoid spamming the log by disabling after we've logged
-            // about this interface at least once
-            mWarnOnBlocking = false;
-            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
-                    new Throwable());
-        }
-
-        final boolean tracingEnabled = Binder.isTracingEnabled();
-        if (tracingEnabled) {
-            final Throwable tr = new Throwable();
-            Binder.getTransactionTracker().addTrace(tr);
-            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
-            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
-                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
-        }
-        try {
-            return transactNative(code, data, reply, flags);
-        } finally {
-            if (tracingEnabled) {
-                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
-            }
-        }
-    }
-
-    private static native long getNativeFinalizer();
-    public native String getInterfaceDescriptor() throws RemoteException;
-    public native boolean transactNative(int code, Parcel data, Parcel reply,
-            int flags) throws RemoteException;
-    public native void linkToDeath(DeathRecipient recipient, int flags)
-            throws RemoteException;
-    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
-
-    public void dump(FileDescriptor fd, String[] args) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeFileDescriptor(fd);
-        data.writeStringArray(args);
-        try {
-            transact(DUMP_TRANSACTION, data, reply, 0);
-            reply.readException();
-        } finally {
-            data.recycle();
-            reply.recycle();
-        }
-    }
-
-    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeFileDescriptor(fd);
-        data.writeStringArray(args);
-        try {
-            transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
-        } finally {
-            data.recycle();
-            reply.recycle();
-        }
-    }
-
-    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ShellCallback callback,
-            ResultReceiver resultReceiver) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeFileDescriptor(in);
-        data.writeFileDescriptor(out);
-        data.writeFileDescriptor(err);
-        data.writeStringArray(args);
-        ShellCallback.writeToParcel(callback, data);
-        resultReceiver.writeToParcel(data, 0);
-        try {
-            transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
-            reply.readException();
-        } finally {
-            data.recycle();
-            reply.recycle();
-        }
-    }
-
-    private static final void sendDeathNotice(DeathRecipient recipient) {
-        if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
-        try {
-            recipient.binderDied();
-        }
-        catch (RuntimeException exc) {
-            Log.w("BinderNative", "Uncaught exception from death notification",
-                    exc);
-        }
-    }
-
-    /**
-     * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
-     * native IBinder object, and a DeathRecipientList.
-     */
-    private final long mNativeData;
-}
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
new file mode 100644
index 0000000..5752b6f
--- /dev/null
+++ b/core/java/android/os/BinderProxy.java
@@ -0,0 +1,588 @@
+/*
+ * Copyright (C) 2006 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 android.os;
+
+import android.annotation.NonNull;
+import android.util.Log;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BinderInternal;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.io.FileDescriptor;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Java proxy for a native IBinder object.
+ * Allocated and constructed by the native javaObjectforIBinder function. Never allocated
+ * directly from Java code.
+ *
+ * @hide
+ */
+public final class BinderProxy implements IBinder {
+    // See android_util_Binder.cpp for the native half of this.
+
+    // Assume the process-wide default value when created
+    volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
+
+    /*
+     * Map from longs to BinderProxy, retaining only a WeakReference to the BinderProxies.
+     * We roll our own only because we need to lazily remove WeakReferences during accesses
+     * to avoid accumulating junk WeakReference objects. WeakHashMap isn't easily usable
+     * because we want weak values, not keys.
+     * Our hash table is never resized, but the number of entries is unlimited;
+     * performance degrades as occupancy increases significantly past MAIN_INDEX_SIZE.
+     * Not thread-safe. Client ensures there's a single access at a time.
+     */
+    private static final class ProxyMap {
+        private static final int LOG_MAIN_INDEX_SIZE = 8;
+        private static final int MAIN_INDEX_SIZE = 1 <<  LOG_MAIN_INDEX_SIZE;
+        private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1;
+        // Debuggable builds will throw an AssertionError if the number of map entries exceeds:
+        private static final int CRASH_AT_SIZE = 20_000;
+
+        /**
+         * We next warn when we exceed this bucket size.
+         */
+        private int mWarnBucketSize = 20;
+
+        /**
+         * Increment mWarnBucketSize by WARN_INCREMENT each time we warn.
+         */
+        private static final int WARN_INCREMENT = 10;
+
+        /**
+         * Hash function tailored to native pointers.
+         * Returns a value < MAIN_INDEX_SIZE.
+         */
+        private static int hash(long arg) {
+            return ((int) ((arg >> 2) ^ (arg >> (2 + LOG_MAIN_INDEX_SIZE)))) & MAIN_INDEX_MASK;
+        }
+
+        /**
+         * Return the total number of pairs in the map.
+         */
+        private int size() {
+            int size = 0;
+            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+                if (a != null) {
+                    size += a.size();
+                }
+            }
+            return size;
+        }
+
+        /**
+         * Return the total number of pairs in the map containing values that have
+         * not been cleared. More expensive than the above size function.
+         */
+        private int unclearedSize() {
+            int size = 0;
+            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+                if (a != null) {
+                    for (WeakReference<BinderProxy> ref : a) {
+                        if (ref.get() != null) {
+                            ++size;
+                        }
+                    }
+                }
+            }
+            return size;
+        }
+
+        /**
+         * Remove ith entry from the hash bucket indicated by hash.
+         */
+        private void remove(int hash, int index) {
+            Long[] keyArray = mMainIndexKeys[hash];
+            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[hash];
+            int size = valueArray.size();  // KeyArray may have extra elements.
+            // Move last entry into empty slot, and truncate at end.
+            if (index != size - 1) {
+                keyArray[index] = keyArray[size - 1];
+                valueArray.set(index, valueArray.get(size - 1));
+            }
+            valueArray.remove(size - 1);
+            // Just leave key array entry; it's unused. We only trust the valueArray size.
+        }
+
+        /**
+         * Look up the supplied key. If we have a non-cleared entry for it, return it.
+         */
+        BinderProxy get(long key) {
+            int myHash = hash(key);
+            Long[] keyArray = mMainIndexKeys[myHash];
+            if (keyArray == null) {
+                return null;
+            }
+            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
+            int bucketSize = valueArray.size();
+            for (int i = 0; i < bucketSize; ++i) {
+                long foundKey = keyArray[i];
+                if (key == foundKey) {
+                    WeakReference<BinderProxy> wr = valueArray.get(i);
+                    BinderProxy bp = wr.get();
+                    if (bp != null) {
+                        return bp;
+                    } else {
+                        remove(myHash, i);
+                        return null;
+                    }
+                }
+            }
+            return null;
+        }
+
+        private int mRandom;  // A counter used to generate a "random" index. World's 2nd worst RNG.
+
+        /**
+         * Add the key-value pair to the map.
+         * Requires that the indicated key is not already in the map.
+         */
+        void set(long key, @NonNull BinderProxy value) {
+            int myHash = hash(key);
+            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
+            if (valueArray == null) {
+                valueArray = mMainIndexValues[myHash] = new ArrayList<>();
+                mMainIndexKeys[myHash] = new Long[1];
+            }
+            int size = valueArray.size();
+            WeakReference<BinderProxy> newWr = new WeakReference<>(value);
+            // First look for a cleared reference.
+            // This ensures that ArrayList size is bounded by the maximum occupancy of
+            // that bucket.
+            for (int i = 0; i < size; ++i) {
+                if (valueArray.get(i).get() == null) {
+                    valueArray.set(i, newWr);
+                    Long[] keyArray = mMainIndexKeys[myHash];
+                    keyArray[i] = key;
+                    if (i < size - 1) {
+                        // "Randomly" check one of the remaining entries in [i+1, size), so that
+                        // needlessly long buckets are eventually pruned.
+                        int rnd = Math.floorMod(++mRandom, size - (i + 1));
+                        if (valueArray.get(i + 1 + rnd).get() == null) {
+                            remove(myHash, i + 1 + rnd);
+                        }
+                    }
+                    return;
+                }
+            }
+            valueArray.add(size, newWr);
+            Long[] keyArray = mMainIndexKeys[myHash];
+            if (keyArray.length == size) {
+                // size >= 1, since we initially allocated one element
+                Long[] newArray = new Long[size + size / 2 + 2];
+                System.arraycopy(keyArray, 0, newArray, 0, size);
+                newArray[size] = key;
+                mMainIndexKeys[myHash] = newArray;
+            } else {
+                keyArray[size] = key;
+            }
+            if (size >= mWarnBucketSize) {
+                final int totalSize = size();
+                Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
+                        + " total = " + totalSize);
+                mWarnBucketSize += WARN_INCREMENT;
+                if (Build.IS_DEBUGGABLE && totalSize >= CRASH_AT_SIZE) {
+                    // Use the number of uncleared entries to determine whether we should
+                    // really report a histogram and crash. We don't want to fundamentally
+                    // change behavior for a debuggable process, so we GC only if we are
+                    // about to crash.
+                    final int totalUnclearedSize = unclearedSize();
+                    if (totalUnclearedSize >= CRASH_AT_SIZE) {
+                        dumpProxyInterfaceCounts();
+                        dumpPerUidProxyCounts();
+                        Runtime.getRuntime().gc();
+                        throw new AssertionError("Binder ProxyMap has too many entries: "
+                                + totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
+                                + unclearedSize() + " (uncleared after GC). BinderProxy leak?");
+                    } else if (totalSize > 3 * totalUnclearedSize / 2) {
+                        Log.v(Binder.TAG, "BinderProxy map has many cleared entries: "
+                                + (totalSize - totalUnclearedSize) + " of " + totalSize
+                                + " are cleared");
+                    }
+                }
+            }
+        }
+
+        private InterfaceCount[] getSortedInterfaceCounts(int maxToReturn) {
+            if (maxToReturn < 0) {
+                throw new IllegalArgumentException("negative interface count");
+            }
+
+            Map<String, Integer> counts = new HashMap<>();
+            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+                if (a != null) {
+                    for (WeakReference<BinderProxy> weakRef : a) {
+                        BinderProxy bp = weakRef.get();
+                        String key;
+                        if (bp == null) {
+                            key = "<cleared weak-ref>";
+                        } else {
+                            try {
+                                key = bp.getInterfaceDescriptor();
+                            } catch (Throwable t) {
+                                key = "<exception during getDescriptor>";
+                            }
+                        }
+                        Integer i = counts.get(key);
+                        if (i == null) {
+                            counts.put(key, 1);
+                        } else {
+                            counts.put(key, i + 1);
+                        }
+                    }
+                }
+            }
+            Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
+                    new Map.Entry[counts.size()]);
+
+            Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b)
+                    -> b.getValue().compareTo(a.getValue()));
+
+            int returnCount = Math.min(maxToReturn, sorted.length);
+            InterfaceCount[] ifaceCounts = new InterfaceCount[returnCount];
+            for (int i = 0; i < returnCount; i++) {
+                ifaceCounts[i] = new InterfaceCount(sorted[i].getKey(), sorted[i].getValue());
+            }
+            return ifaceCounts;
+        }
+
+        static final int MAX_NUM_INTERFACES_TO_DUMP = 10;
+
+        /**
+         * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
+         */
+        private void dumpProxyInterfaceCounts() {
+            final InterfaceCount[] sorted = getSortedInterfaceCounts(MAX_NUM_INTERFACES_TO_DUMP);
+
+            Log.v(Binder.TAG, "BinderProxy descriptor histogram "
+                    + "(top " + Integer.toString(MAX_NUM_INTERFACES_TO_DUMP) + "):");
+            for (int i = 0; i < sorted.length; i++) {
+                Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i]);
+            }
+        }
+
+        /**
+         * Dump per uid binder proxy counts to the logcat.
+         */
+        private void dumpPerUidProxyCounts() {
+            SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
+            if (counts.size() == 0) return;
+            Log.d(Binder.TAG, "Per Uid Binder Proxy Counts:");
+            for (int i = 0; i < counts.size(); i++) {
+                final int uid = counts.keyAt(i);
+                final int binderCount = counts.valueAt(i);
+                Log.d(Binder.TAG, "UID : " + uid + "  count = " + binderCount);
+            }
+        }
+
+        // Corresponding ArrayLists in the following two arrays always have the same size.
+        // They contain no empty entries. However WeakReferences in the values ArrayLists
+        // may have been cleared.
+
+        // mMainIndexKeys[i][j] corresponds to mMainIndexValues[i].get(j) .
+        // The values ArrayList has the proper size(), the corresponding keys array
+        // is always at least the same size, but may be larger.
+        // If either a particular keys array, or the corresponding values ArrayList
+        // are null, then they both are.
+        private final Long[][] mMainIndexKeys = new Long[MAIN_INDEX_SIZE][];
+        private final ArrayList<WeakReference<BinderProxy>>[] mMainIndexValues =
+                new ArrayList[MAIN_INDEX_SIZE];
+    }
+
+    @GuardedBy("sProxyMap")
+    private static final ProxyMap sProxyMap = new ProxyMap();
+
+    /**
+     * Simple pair-value class to store number of binder proxy interfaces live in this process.
+     */
+    public static final class InterfaceCount {
+        private final String mInterfaceName;
+        private final int mCount;
+
+        InterfaceCount(String interfaceName, int count) {
+            mInterfaceName = interfaceName;
+            mCount = count;
+        }
+
+        @Override
+        public String toString() {
+            return mInterfaceName + " x" + Integer.toString(mCount);
+        }
+    }
+
+    /**
+     * Get a sorted array with entries mapping proxy interface names to the number
+     * of live proxies with those names.
+     *
+     * @param num maximum number of proxy interface counts to return. Use
+     *            Integer.MAX_VALUE to retrieve all
+     * @hide
+     */
+    public static InterfaceCount[] getSortedInterfaceCounts(int num) {
+        synchronized (sProxyMap) {
+            return sProxyMap.getSortedInterfaceCounts(num);
+        }
+    }
+
+    /**
+     * Dump proxy debug information.
+     *
+     * @hide
+     */
+    public static void dumpProxyDebugInfo() {
+        if (Build.IS_DEBUGGABLE) {
+            synchronized (sProxyMap) {
+                sProxyMap.dumpProxyInterfaceCounts();
+                sProxyMap.dumpPerUidProxyCounts();
+            }
+        }
+    }
+
+    /**
+     * Return a BinderProxy for IBinder.
+     * If we previously returned a BinderProxy bp for the same iBinder, and bp is still
+     * in use, then we return the same bp.
+     *
+     * @param nativeData C++ pointer to (possibly still empty) BinderProxyNativeData.
+     * Takes ownership of nativeData iff <result>.mNativeData == nativeData, or if
+     * we exit via an exception.  If neither applies, it's the callers responsibility to
+     * recycle nativeData.
+     * @param iBinder C++ pointer to IBinder. Does not take ownership of referenced object.
+     */
+    private static BinderProxy getInstance(long nativeData, long iBinder) {
+        BinderProxy result;
+        synchronized (sProxyMap) {
+            try {
+                result = sProxyMap.get(iBinder);
+                if (result != null) {
+                    return result;
+                }
+                result = new BinderProxy(nativeData);
+            } catch (Throwable e) {
+                // We're throwing an exception (probably OOME); don't drop nativeData.
+                NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
+                        nativeData);
+                throw e;
+            }
+            NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
+            // The registry now owns nativeData, even if registration threw an exception.
+            sProxyMap.set(iBinder, result);
+        }
+        return result;
+    }
+
+    private BinderProxy(long nativeData) {
+        mNativeData = nativeData;
+    }
+
+    /**
+     * Guestimate of native memory associated with a BinderProxy.
+     * This includes the underlying IBinder, associated DeathRecipientList, and KeyedVector
+     * that points back to us. We guess high since it includes a GlobalRef, which
+     * may be in short supply.
+     */
+    private static final int NATIVE_ALLOCATION_SIZE = 1000;
+
+    // Use a Holder to allow static initialization of BinderProxy in the boot image, and
+    // to avoid some initialization ordering issues.
+    private static class NoImagePreloadHolder {
+        public static final long sNativeFinalizer = getNativeFinalizer();
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                BinderProxy.class.getClassLoader(), sNativeFinalizer, NATIVE_ALLOCATION_SIZE);
+    }
+
+    /**
+     * @return false if the hosting process is gone, otherwise whatever the remote returns
+     */
+    public native boolean pingBinder();
+
+    /**
+     * @return false if the hosting process is gone
+     */
+    public native boolean isBinderAlive();
+
+    /**
+     * Retrieve a local interface - always null in case of a proxy
+     */
+    public IInterface queryLocalInterface(String descriptor) {
+        return null;
+    }
+
+    /**
+     * Perform a binder transaction on a proxy.
+     *
+     * @param code The action to perform.  This should
+     * be a number between {@link #FIRST_CALL_TRANSACTION} and
+     * {@link #LAST_CALL_TRANSACTION}.
+     * @param data Marshalled data to send to the target.  Must not be null.
+     * If you are not sending any data, you must create an empty Parcel
+     * that is given here.
+     * @param reply Marshalled data to be received from the target.  May be
+     * null if you are not interested in the return value.
+     * @param flags Additional operation flags.  Either 0 for a normal
+     * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
+     *
+     * @return
+     * @throws RemoteException
+     */
+    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
+        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
+
+        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
+            // For now, avoid spamming the log by disabling after we've logged
+            // about this interface at least once
+            mWarnOnBlocking = false;
+            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
+                    new Throwable());
+        }
+
+        final boolean tracingEnabled = Binder.isTracingEnabled();
+        if (tracingEnabled) {
+            final Throwable tr = new Throwable();
+            Binder.getTransactionTracker().addTrace(tr);
+            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
+            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
+                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
+        }
+        try {
+            return transactNative(code, data, reply, flags);
+        } finally {
+            if (tracingEnabled) {
+                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
+            }
+        }
+    }
+
+    /* Returns the native free function */
+    private static native long getNativeFinalizer();
+    /**
+     *  See {@link IBinder#getInterfaceDescriptor()}
+     */
+    public native String getInterfaceDescriptor() throws RemoteException;
+
+    /**
+     * Native implementation of transact() for proxies
+     */
+    public native boolean transactNative(int code, Parcel data, Parcel reply,
+            int flags) throws RemoteException;
+    /**
+     * See {@link IBinder#linkToDeath(DeathRecipient, int)}
+     */
+    public native void linkToDeath(DeathRecipient recipient, int flags)
+            throws RemoteException;
+    /**
+     * See {@link IBinder#unlinkToDeath}
+     */
+    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
+
+    /**
+     * Perform a dump on the remote object
+     *
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param args additional arguments to the dump request.
+     * @throws RemoteException
+     */
+    public void dump(FileDescriptor fd, String[] args) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeFileDescriptor(fd);
+        data.writeStringArray(args);
+        try {
+            transact(DUMP_TRANSACTION, data, reply, 0);
+            reply.readException();
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
+    }
+
+    /**
+     * Perform an asynchronous dump on the remote object
+     *
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param args additional arguments to the dump request.
+     * @throws RemoteException
+     */
+    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeFileDescriptor(fd);
+        data.writeStringArray(args);
+        try {
+            transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
+    }
+
+    /**
+     * See {@link IBinder#shellCommand(FileDescriptor, FileDescriptor, FileDescriptor,
+     * String[], ShellCallback, ResultReceiver)}
+     *
+     * @param in The raw file descriptor that an input data stream can be read from.
+     * @param out The raw file descriptor that normal command messages should be written to.
+     * @param err The raw file descriptor that command error messages should be written to.
+     * @param args Command-line arguments.
+     * @param callback Optional callback to the caller's shell to perform operations in it.
+     * @param resultReceiver Called when the command has finished executing, with the result code.
+     * @throws RemoteException
+     */
+    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeFileDescriptor(in);
+        data.writeFileDescriptor(out);
+        data.writeFileDescriptor(err);
+        data.writeStringArray(args);
+        ShellCallback.writeToParcel(callback, data);
+        resultReceiver.writeToParcel(data, 0);
+        try {
+            transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
+            reply.readException();
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
+    }
+
+    private static void sendDeathNotice(DeathRecipient recipient) {
+        if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
+        try {
+            recipient.binderDied();
+        } catch (RuntimeException exc) {
+            Log.w("BinderNative", "Uncaught exception from death notification",
+                    exc);
+        }
+    }
+
+    /**
+     * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
+     * native IBinder object, and a DeathRecipientList.
+     */
+    private final long mNativeData;
+}
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index 369f357..027ead3 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -437,7 +437,6 @@
     public boolean canUseMeasuredResult(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
             @NonNull TextDirectionHeuristic textDir, @NonNull TextPaint paint,
             @Layout.BreakStrategy int strategy, @Layout.HyphenationFrequency int frequency) {
-        final TextPaint mtPaint = mParams.getTextPaint();
         return mStart == start
             && mEnd == end
             && mParams.isSameTextMetricsInternal(paint, textDir, strategy, frequency);
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 621a745..2b1e900 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -30,7 +30,6 @@
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
-import android.icu.util.Calendar;
 import android.os.Handler;
 import android.text.format.Time;
 import android.util.AttributeSet;
@@ -41,6 +40,7 @@
 
 import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 
@@ -301,7 +301,7 @@
      */
     private long computeNextMidnight(TimeZone timeZone) {
         Calendar c = Calendar.getInstance();
-        c.setTimeZone(libcore.icu.DateUtilsBridge.icuTimeZone(timeZone));
+        c.setTimeZone(timeZone);
         c.add(Calendar.DAY_OF_MONTH, 1);
         c.set(Calendar.HOUR_OF_DAY, 0);
         c.set(Calendar.MINUTE, 0);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2e7ef8b..ea54696 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6973,7 +6973,8 @@
     public boolean hasOverlappingRendering() {
         // horizontal fading edge causes SaveLayerAlpha, which doesn't support alpha modulation
         return ((getBackground() != null && getBackground().getCurrent() != null)
-                || mSpannable != null || hasSelection() || isHorizontalFadingEdgeEnabled());
+                || mSpannable != null || hasSelection() || isHorizontalFadingEdgeEnabled()
+                || mShadowColor != 0);
     }
 
     /**
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index d247013..1d997f5 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -21,6 +21,7 @@
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 
+import java.io.Serializable;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.IllformedLocaleException;
@@ -31,7 +32,7 @@
     private static final HashMap<String, LocaleInfo> sLocaleCache = new HashMap<>();
     private static boolean sFullyInitialized = false;
 
-    public static class LocaleInfo {
+    public static class LocaleInfo implements Serializable {
         private static final int SUGGESTION_TYPE_NONE = 0;
         private static final int SUGGESTION_TYPE_SIM = 1 << 0;
         private static final int SUGGESTION_TYPE_CFG = 1 << 1;
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 7e2bad2..ecad6c0 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -108,7 +108,6 @@
     jclass mClass;
     jmethodID mGetInstance;
     jmethodID mSendDeathNotice;
-    jmethodID mDumpProxyDebugInfo;
 
     // Object state.
     jfieldID mNativeData;  // Field holds native pointer to BinderProxyNativeData.
@@ -994,16 +993,6 @@
 static void android_os_BinderInternal_proxyLimitcallback(int uid)
 {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    {
-        env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
-                                    gBinderProxyOffsets.mDumpProxyDebugInfo);
-    }
-    if (env->ExceptionCheck()) {
-        ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
-        report_exception(env, excep.get(),
-            "*** Uncaught exception in dumpProxyDebugInfo");
-    }
-
     env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
                               gBinderInternalOffsets.mProxyLimitCallback,
                               uid);
@@ -1390,8 +1379,6 @@
             "(JJ)Landroid/os/BinderProxy;");
     gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
             "(Landroid/os/IBinder$DeathRecipient;)V");
-    gBinderProxyOffsets.mDumpProxyDebugInfo = GetStaticMethodIDOrDie(env, clazz, "dumpProxyDebugInfo",
-            "()V");
     gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
 
     clazz = FindClassOrDie(env, "java/lang/Class");
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 15dbbc8..c98e646 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -20,6 +20,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.util.KeyUtils;
 import android.view.KeyEvent;
@@ -238,6 +239,7 @@
     }
 
     @Test
+    @Suppress
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
@@ -267,6 +269,7 @@
     }
 
     @Test
+    @Suppress
     public void testMixedEdgeCases() {
         EditorState state = new EditorState();
 
diff --git a/libs/androidfw/ChunkIterator.cpp b/libs/androidfw/ChunkIterator.cpp
index d8adbe5..8fc3219 100644
--- a/libs/androidfw/ChunkIterator.cpp
+++ b/libs/androidfw/ChunkIterator.cpp
@@ -32,11 +32,30 @@
 
   if (len_ != 0) {
     // Prepare the next chunk.
-    VerifyNextChunk();
+    if (VerifyNextChunkNonFatal()) {
+      VerifyNextChunk();
+    }
   }
   return Chunk(this_chunk);
 }
 
+// TODO(b/111401637) remove this and have full resource file verification
+// Returns false if there was an error.
+bool ChunkIterator::VerifyNextChunkNonFatal() {
+  if (len_ < sizeof(ResChunk_header)) {
+    last_error_ = "not enough space for header";
+    last_error_was_fatal_ = false;
+    return false;
+  }
+  const size_t size = dtohl(next_chunk_->size);
+  if (size > len_) {
+    last_error_ = "chunk size is bigger than given data";
+    last_error_was_fatal_ = false;
+    return false;
+  }
+  return true;
+}
+
 // Returns false if there was an error.
 bool ChunkIterator::VerifyNextChunk() {
   const uintptr_t header_start = reinterpret_cast<uintptr_t>(next_chunk_);
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 04d506a..c2740c9 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -560,7 +560,9 @@
 
   if (iter.HadError()) {
     LOG(ERROR) << iter.GetLastError();
-    return {};
+    if (iter.HadFatalError()) {
+      return {};
+    }
   }
 
   // Flatten and construct the TypeSpecs.
@@ -641,7 +643,9 @@
 
   if (iter.HadError()) {
     LOG(ERROR) << iter.GetLastError();
-    return false;
+    if (iter.HadFatalError()) {
+      return false;
+    }
   }
   return true;
 }
@@ -673,7 +677,9 @@
 
   if (iter.HadError()) {
     LOG(ERROR) << iter.GetLastError();
-    return {};
+    if (iter.HadFatalError()) {
+      return {};
+    }
   }
 
   // Need to force a move for mingw32.
diff --git a/libs/androidfw/include/androidfw/Chunk.h b/libs/androidfw/include/androidfw/Chunk.h
index 89b588e..99a52dc 100644
--- a/libs/androidfw/include/androidfw/Chunk.h
+++ b/libs/androidfw/include/androidfw/Chunk.h
@@ -94,18 +94,27 @@
 
   Chunk Next();
   inline bool HasNext() const { return !HadError() && len_ != 0; };
+  // Returns whether there was an error and processing should stop
   inline bool HadError() const { return last_error_ != nullptr; }
   inline std::string GetLastError() const { return last_error_; }
+  // Returns whether there was an error and processing should stop. For legacy purposes,
+  // some errors are considered "non fatal". Fatal errors stop processing new chunks and
+  // throw away any chunks already processed. Non fatal errors also stop processing new
+  // chunks, but, will retain and use any valid chunks already processed.
+  inline bool HadFatalError() const { return HadError() && last_error_was_fatal_; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ChunkIterator);
 
   // Returns false if there was an error.
   bool VerifyNextChunk();
+  // Returns false if there was an error. For legacy purposes.
+  bool VerifyNextChunkNonFatal();
 
   const ResChunk_header* next_chunk_;
   size_t len_;
   const char* last_error_;
+  bool last_error_was_fatal_ = true;
 };
 
 }  // namespace android
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 14d31b2..c41f6a6 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -82,7 +82,14 @@
             textureMatrix = textureMatrixInv;
         }
 
-        SkMatrix matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+        SkMatrix matrix;
+        if (dstRect) {
+            // Destination rectangle is set only when we are trying to read back the content
+            // of the layer. In this case we don't want to apply layer transform.
+            matrix = textureMatrix;
+        } else {
+            matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+        }
 
         SkPaint paint;
         paint.setAlpha(layer->getAlpha());
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 10edf73..a19edae 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -327,8 +327,6 @@
         }
         return vkGetInstanceProcAddr(instance, proc_name);
     };
-    auto interface =
-        sk_make_sp<GrVkInterface>(getProc, mInstance, mDevice, extensionFlags);
 
     GrVkBackendContext backendContext;
     backendContext.fInstance = mInstance;
@@ -339,7 +337,7 @@
     backendContext.fMinAPIVersion = VK_MAKE_VERSION(1, 0, 0);
     backendContext.fExtensions = extensionFlags;
     backendContext.fFeatures = featureFlags;
-    backendContext.fInterface = std::move(interface);
+    backendContext.fGetProc = std::move(getProc);
     backendContext.fOwnsInstanceAndDevice = false;
 
     // create the command pool for the command buffers
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 6eb3d8d..ee9e732 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,7 +22,6 @@
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
 import android.Manifest;
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -42,16 +41,11 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.ArraySet;
 import android.util.Log;
 import com.android.internal.location.ProviderProperties;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Set;
 
 /**
  * This class provides access to the system location services.  These
@@ -331,7 +325,7 @@
             Message msg = Message.obtain();
             msg.what = TYPE_LOCATION_CHANGED;
             msg.obj = location;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
         }
 
         @Override
@@ -345,7 +339,7 @@
                 b.putBundle("extras", extras);
             }
             msg.obj = b;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
         }
 
         @Override
@@ -353,7 +347,7 @@
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_ENABLED;
             msg.obj = provider;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
         }
 
         @Override
@@ -361,7 +355,13 @@
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_DISABLED;
             msg.obj = provider;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
+        }
+
+        private void sendCallbackMessage(Message msg) {
+            if (!mListenerHandler.sendMessage(msg)) {
+                locationCallbackFinished();
+            }
         }
 
         private void _handleMessage(Message msg) {
@@ -384,6 +384,10 @@
                     mListener.onProviderDisabled((String) msg.obj);
                     break;
             }
+            locationCallbackFinished();
+        }
+
+        private void locationCallbackFinished() {
             try {
                 mService.locationCallbackFinished(this);
             } catch (RemoteException e) {
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 7c68b55..2a2f4fe 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -143,7 +143,7 @@
      * MIME type for HEIF still image data encoded in HEVC.
      *
      * To decode such an image, {@link MediaCodec} decoder for
-     * {@ #MIMETYPE_VIDEO_HEVC} shall be used. The client needs to form
+     * {@link #MIMETYPE_VIDEO_HEVC} shall be used. The client needs to form
      * the correct {@link #MediaFormat} based on additional information in
      * the track format, and send it to {@link MediaCodec#configure}.
      *
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ada91be..d532e52 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2510,10 +2510,10 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mTrackType);
+            dest.writeString(mFormat.getString(MediaFormat.KEY_MIME));
             dest.writeString(getLanguage());
 
             if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                dest.writeString(mFormat.getString(MediaFormat.KEY_MIME));
                 dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_AUTOSELECT));
                 dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_DEFAULT));
                 dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE));
diff --git a/packages/SystemUI/res/layout/contextual.xml b/packages/SystemUI/res/layout/contextual.xml
index 94591e9..c8f0a24 100644
--- a/packages/SystemUI/res/layout/contextual.xml
+++ b/packages/SystemUI/res/layout/contextual.xml
@@ -20,6 +20,7 @@
              android:layout_width="@dimen/navigation_key_width"
              android:layout_height="match_parent"
              android:importantForAccessibility="no"
+             android:focusable="false"
              android:clipChildren="false"
              android:clipToPadding="false"
              >
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 9130fb4..8a3a0b1 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -17,13 +17,13 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/menu_container"
-    android:layout_width="match_parent"
+    android:layout_width="@dimen/navigation_key_width"
     android:layout_height="match_parent"
     android:importantForAccessibility="no"
     >
-    <!-- Use width & height=match_parent for parent FrameLayout and buttons because they are placed
-    inside a view that has a size controlled by weight. Ensure weight is large enough to support
-    icon size. -->
+    <!-- Use nav button width & height=match_parent for parent FrameLayout and buttons because they
+    are placed inside a view that has a size controlled by weight. Ensure weight is large enough to
+    support icon size. -->
 
     <com.android.systemui.statusbar.policy.KeyButtonView
         android:id="@+id/menu"
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index cd1bd67..574288a 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -38,6 +38,7 @@
 import android.app.IActivityManager;
 import android.app.IBackupAgent;
 import android.app.PendingIntent;
+import android.app.backup.BackupAgent;
 import android.app.backup.BackupManager;
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.FullBackup;
@@ -704,7 +705,7 @@
      * process-local non-lifecycle agent instance, so we manually set up the context
      * topology for it.
      */
-    public PackageManagerBackupAgent makeMetadataAgent() {
+    public BackupAgent makeMetadataAgent() {
         PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager);
         pmAgent.attach(mContext);
         pmAgent.onCreate();
@@ -784,7 +785,7 @@
     }
 
     @VisibleForTesting
-    BackupManagerService(
+    public BackupManagerService(
             Context context,
             Trampoline parent,
             HandlerThread backupThread,
@@ -1749,6 +1750,16 @@
         }
     }
 
+    public void putOperation(int token, Operation operation) {
+        if (MORE_DEBUG) {
+            Slog.d(TAG, "Adding operation token=" + Integer.toHexString(token) + ", operation type="
+                    + operation.type);
+        }
+        synchronized (mCurrentOpLock) {
+            mCurrentOperations.put(token, operation);
+        }
+    }
+
     public void removeOperation(int token) {
         if (MORE_DEBUG) {
             Slog.d(TAG, "Removing operation token=" + Integer.toHexString(token));
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index ae43299..90b4bbd 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -30,6 +30,7 @@
 import android.annotation.Nullable;
 import android.app.ApplicationThreadConstants;
 import android.app.IBackupAgent;
+import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
 import android.app.backup.BackupManager;
@@ -205,10 +206,8 @@
      * Put this task in the repository of running tasks.
      */
     private void registerTask() {
-        synchronized (backupManagerService.getCurrentOpLock()) {
-            backupManagerService.getCurrentOperations().put(
-                    mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP));
-        }
+        backupManagerService.putOperation(
+                mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP));
     }
 
     /**
@@ -358,7 +357,7 @@
             // The package manager doesn't have a proper <application> etc, but since it's running
             // here in the system process we can just set up its agent directly and use a synthetic
             // BackupRequest.
-            PackageManagerBackupAgent pmAgent = backupManagerService.makeMetadataAgent();
+            BackupAgent pmAgent = backupManagerService.makeMetadataAgent();
             mStatus = invokeAgentForBackup(
                     PACKAGE_MANAGER_SENTINEL,
                     IBackupAgent.Stub.asInterface(pmAgent.onBind()));
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 78b000d..32dbad9 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -30,6 +30,7 @@
 
 
 import android.app.IBackupAgent;
+import android.app.backup.BackupAgent;
 import android.app.backup.IFullBackupRestoreObserver;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.Signature;
@@ -76,7 +77,7 @@
     private final String mCurrentPassword;
     private final String mDecryptPassword;
     private final AtomicBoolean mLatchObject;
-    private final PackageManagerBackupAgent mPackageManagerBackupAgent;
+    private final BackupAgent mPackageManagerBackupAgent;
     private final RestoreDeleteObserver mDeleteObserver = new RestoreDeleteObserver();
 
     private IFullBackupRestoreObserver mObserver;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 776cf47..232c151 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -795,6 +795,7 @@
      * location updates.
      */
     private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
+        private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
         final Identity mIdentity;
         final int mAllowedResolutionLevel;  // resolution level allowed to receiver
 
@@ -838,6 +839,10 @@
                 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
             }
             mWakeLock.setWorkSource(workSource);
+
+            // For a non-reference counted wakelock, each acquire will reset the timeout, and we
+            // only need to release it once.
+            mWakeLock.setReferenceCounted(false);
         }
 
         @Override
@@ -1099,9 +1104,8 @@
         // this must be called while synchronized by caller in a synchronized block
         // containing the sending of the broadcaset
         private void incrementPendingBroadcastsLocked() {
-            if (mPendingBroadcasts++ == 0) {
-                mWakeLock.acquire();
-            }
+            mPendingBroadcasts++;
+            mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
         }
 
         private void decrementPendingBroadcastsLocked() {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 59093c1..e7a8221 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.system.ErrnoException;
+import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructRlimit;
 import com.android.internal.os.ZygoteConnectionConstants;
@@ -47,6 +48,10 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -621,23 +626,38 @@
             mFdHighWaterMark = fdThreshold;
         }
 
+        /**
+         * Dumps open file descriptors and their full paths to a temporary file in {@code mDumpDir}.
+         */
         private void dumpOpenDescriptors() {
+            // We cannot exec lsof to get more info about open file descriptors because a newly
+            // forked process will not have the permissions to readlink. Instead list all open
+            // descriptors from /proc/pid/fd and resolve them.
+            List<String> dumpInfo = new ArrayList<>();
+            String fdDirPath = String.format("/proc/%d/fd/", Process.myPid());
+            File[] fds = new File(fdDirPath).listFiles();
+            if (fds == null) {
+                dumpInfo.add("Unable to list " + fdDirPath);
+            } else {
+                for (File f : fds) {
+                    String fdSymLink = f.getAbsolutePath();
+                    String resolvedPath = "";
+                    try {
+                        resolvedPath = Os.readlink(fdSymLink);
+                    } catch (ErrnoException ex) {
+                        resolvedPath = ex.getMessage();
+                    }
+                    dumpInfo.add(fdSymLink + "\t" + resolvedPath);
+                }
+            }
+
+            // Dump the fds & paths to a temp file.
             try {
                 File dumpFile = File.createTempFile("anr_fd_", "", mDumpDir);
-                java.lang.Process proc = new ProcessBuilder()
-                    .command("/system/bin/lsof", "-p", String.valueOf(Process.myPid()))
-                    .redirectErrorStream(true)
-                    .redirectOutput(dumpFile)
-                    .start();
-
-                int returnCode = proc.waitFor();
-                if (returnCode != 0) {
-                    Slog.w(TAG, "Unable to dump open descriptors, lsof return code: "
-                        + returnCode);
-                    dumpFile.delete();
-                }
-            } catch (IOException | InterruptedException ex) {
-                Slog.w(TAG, "Unable to dump open descriptors: " + ex);
+                Path out = Paths.get(dumpFile.getAbsolutePath());
+                Files.write(out, dumpInfo, StandardCharsets.UTF_8);
+            } catch (IOException ex) {
+                Slog.w(TAG, "Unable to write open descriptors to file: " + ex);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 48f4b22..f02e8f6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -242,6 +242,7 @@
 import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Binder;
+import android.os.BinderProxy;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
@@ -11577,6 +11578,7 @@
                         public void onLimitReached(int uid) {
                             Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
                                     + Process.myUid());
+                            BinderProxy.dumpProxyDebugInfo();
                             if (uid == Process.SYSTEM_UID) {
                                 Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
                             } else {
@@ -12122,7 +12124,7 @@
         return imp;
     }
 
-    private void fillInProcMemInfo(ProcessRecord app,
+    private void fillInProcMemInfoLocked(ProcessRecord app,
             ActivityManager.RunningAppProcessInfo outInfo,
             int clientTargetSdk) {
         outInfo.pid = app.pid;
@@ -12142,6 +12144,8 @@
         outInfo.importance = procStateToImportance(procState, adj, outInfo, clientTargetSdk);
         outInfo.importanceReasonCode = app.adjTypeCode;
         outInfo.processState = app.curProcState;
+        outInfo.isFocused = (app == getTopAppLocked());
+        outInfo.lastActivityTime = app.lastActivityTime;
     }
 
     @Override
@@ -12172,7 +12176,7 @@
                     ActivityManager.RunningAppProcessInfo currApp =
                         new ActivityManager.RunningAppProcessInfo(app.processName,
                                 app.pid, app.getPackageList());
-                    fillInProcMemInfo(app, currApp, clientTargetSdk);
+                    fillInProcMemInfoLocked(app, currApp, clientTargetSdk);
                     if (app.adjSource instanceof ProcessRecord) {
                         currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
                         currApp.importanceReasonImportance =
@@ -12241,7 +12245,7 @@
                 proc = mPidsSelfLocked.get(Binder.getCallingPid());
             }
             if (proc != null) {
-                fillInProcMemInfo(proc, outState, clientTargetSdk);
+                fillInProcMemInfoLocked(proc, outState, clientTargetSdk);
             }
         }
     }
@@ -12425,8 +12429,10 @@
                 }
             } else if ("binder-proxies".equals(cmd)) {
                 if (opti >= args.length) {
+                    dumpBinderProxyInterfaceCounts(pw,
+                            "Top proxy interface names held by SYSTEM");
                     dumpBinderProxiesCounts(pw, BinderInternal.nGetBinderProxyPerUidCounts(),
-                            "Counts of Binder Proxies held by SYSTEM");
+                            "Number of proxies per uid held by SYSTEM");
                 } else {
                     String uid = args[opti];
                     opti++;
@@ -12964,6 +12970,15 @@
         return printed;
     }
 
+    void dumpBinderProxyInterfaceCounts(PrintWriter pw, String header) {
+        final BinderProxy.InterfaceCount[] proxyCounts = BinderProxy.getSortedInterfaceCounts(50);
+
+        pw.println(header);
+        for (int i = 0; i < proxyCounts.length; i++) {
+            pw.println("    #" + (i + 1) + ": " + proxyCounts[i]);
+        }
+    }
+
     boolean dumpBinderProxiesCounts(PrintWriter pw, SparseIntArray counts, String header) {
         if(counts != null) {
             pw.println(header);
@@ -20697,22 +20712,24 @@
     }
 
     @GuardedBy("this")
+    ProcessRecord getTopAppLocked() {
+        final ActivityRecord TOP_ACT = resumedAppLocked();
+        if (TOP_ACT != null && TOP_ACT.hasProcess()) {
+            return (ProcessRecord) TOP_ACT.app.mOwner;
+        } else {
+            return null;
+        }
+    }
+
+    @GuardedBy("this")
     final void updateOomAdjLocked() {
         mOomAdjProfiler.oomAdjStarted();
-        final ActivityRecord TOP_ACT = resumedAppLocked();
-        final ProcessRecord TOP_APP = TOP_ACT != null && TOP_ACT.hasProcess()
-                ? (ProcessRecord) TOP_ACT.app.mOwner : null;
+        final ProcessRecord TOP_APP = getTopAppLocked();
         final long now = SystemClock.uptimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
         final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
         final int N = mLruProcesses.size();
 
-        if (false) {
-            RuntimeException e = new RuntimeException();
-            e.fillInStackTrace();
-            Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
-        }
-
         // Reset state in all uid records.
         for (int i=mActiveUids.size()-1; i>=0; i--) {
             final UidRecord uidRec = mActiveUids.valueAt(i);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 5105941..84bdbba 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -115,7 +115,6 @@
 import com.android.server.connectivity.tethering.IControlsTethering;
 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
 import com.android.server.connectivity.tethering.OffloadController;
-import com.android.server.connectivity.tethering.SimChangeListener;
 import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
 import com.android.server.connectivity.tethering.TetheringConfiguration;
 import com.android.server.connectivity.tethering.TetheringDependencies;
@@ -201,8 +200,6 @@
     // into a single coherent structure.
     private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
     private final VersionedBroadcastListener mCarrierConfigChange;
-    // TODO: Delete SimChangeListener; it's obsolete.
-    private final SimChangeListener mSimChange;
     private final TetheringDependencies mDeps;
 
     private volatile TetheringConfiguration mConfig;
@@ -252,14 +249,6 @@
                     updateConfiguration();
                     reevaluateSimCardProvisioning();
                 });
-        // TODO: Remove SimChangeListener altogether. For now, we retain it
-        // for logging purposes in case we need to debug something that might
-        // be related to changing signals from ACTION_SIM_STATE_CHANGED to
-        // ACTION_CARRIER_CONFIG_CHANGED.
-        mSimChange = new SimChangeListener(
-                mContext, smHandler, () -> {
-                    mLog.log("OBSERVED SIM card change");
-                });
 
         mStateReceiver = new StateReceiver();
 
@@ -1530,7 +1519,6 @@
                     return;
                 }
 
-                mSimChange.startListening();
                 mUpstreamNetworkMonitor.start(mDeps.getDefaultNetworkRequest());
 
                 // TODO: De-duplicate with updateUpstreamWanted() below.
@@ -1546,7 +1534,6 @@
             public void exit() {
                 mOffload.stop();
                 mUpstreamNetworkMonitor.stop();
-                mSimChange.stopListening();
                 notifyDownstreamsOfNewUpstreamIface(null);
                 handleNewUpstreamNetworkState(null);
             }
diff --git a/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java b/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java
deleted file mode 100644
index 33c9355..0000000
--- a/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.connectivity.tethering;
-
-import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_LOADED;
-import static com.android.internal.telephony.IccCardConstants.INTENT_KEY_ICC_STATE;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.util.VersionedBroadcastListener;
-import android.net.util.VersionedBroadcastListener.IntentCallback;
-import android.os.Handler;
-import android.util.Log;
-
-import com.android.internal.telephony.TelephonyIntents;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-
-
-/**
- * A utility class that runs the provided callback on the provided handler when
- * observing a new SIM card having been loaded.
- *
- * @hide
- */
-public class SimChangeListener extends VersionedBroadcastListener {
-    private static final String TAG = SimChangeListener.class.getSimpleName();
-    private static final boolean DBG = false;
-
-    public SimChangeListener(Context ctx, Handler handler, Runnable onSimCardLoadedCallback) {
-        super(TAG, ctx, handler, makeIntentFilter(), makeCallback(onSimCardLoadedCallback));
-    }
-
-    private static IntentFilter makeIntentFilter() {
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
-        return filter;
-    }
-
-    private static Consumer<Intent> makeCallback(Runnable onSimCardLoadedCallback) {
-        return new Consumer<Intent>() {
-            private boolean mSimNotLoadedSeen = false;
-
-            @Override
-            public void accept(Intent intent) {
-                final String state = intent.getStringExtra(INTENT_KEY_ICC_STATE);
-                Log.d(TAG, "got Sim changed to state " + state + ", mSimNotLoadedSeen=" +
-                        mSimNotLoadedSeen);
-
-                if (!INTENT_VALUE_ICC_LOADED.equals(state)) {
-                    mSimNotLoadedSeen = true;
-                    return;
-                }
-
-                if (mSimNotLoadedSeen) {
-                    mSimNotLoadedSeen = false;
-                    onSimCardLoadedCallback.run();
-                }
-            }
-        };
-    }
-}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c6a8712..adfa8d5 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2012,7 +2012,7 @@
         enforceShell();
         final long origId = Binder.clearCallingIdentity();
         try {
-            (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec(
+            (new LockSettingsShellCommand(new LockPatternUtils(mContext))).exec(
                     this, in, out, err, args, callback, resultReceiver);
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index 4d2cf32..085d17d 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -21,13 +21,13 @@
 import static com.android.internal.widget.LockPatternUtils.stringToPattern;
 
 import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
 import android.os.ShellCommand;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 
+import java.io.PrintWriter;
+
 class LockSettingsShellCommand extends ShellCommand {
 
     private static final String COMMAND_SET_PATTERN = "set-pattern";
@@ -38,20 +38,22 @@
     private static final String COMMAND_SET_DISABLED = "set-disabled";
     private static final String COMMAND_VERIFY = "verify";
     private static final String COMMAND_GET_DISABLED = "get-disabled";
+    private static final String COMMAND_HELP = "help";
 
     private int mCurrentUserId;
     private final LockPatternUtils mLockPatternUtils;
-    private final Context mContext;
     private String mOld = "";
     private String mNew = "";
 
-    LockSettingsShellCommand(Context context, LockPatternUtils lockPatternUtils) {
-        mContext = context;
+    LockSettingsShellCommand(LockPatternUtils lockPatternUtils) {
         mLockPatternUtils = lockPatternUtils;
     }
 
     @Override
     public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
         try {
             mCurrentUserId = ActivityManager.getService().getCurrentUser().id;
 
@@ -84,6 +86,9 @@
                 case COMMAND_GET_DISABLED:
                     runGetDisabled();
                     break;
+                case COMMAND_HELP:
+                    onHelp();
+                    break;
                 default:
                     getErrPrintWriter().println("Unknown command: " + cmd);
                     break;
@@ -103,6 +108,43 @@
 
     @Override
     public void onHelp() {
+        try (final PrintWriter pw = getOutPrintWriter();) {
+            pw.println("lockSettings service commands:");
+            pw.println("");
+            pw.println("NOTE: when lock screen is set, all commands require the --old <CREDENTIAL>"
+                    + " argument.");
+            pw.println("");
+            pw.println("  help");
+            pw.println("    Prints this help text.");
+            pw.println("");
+            pw.println("  get-disabled [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Checks whether lock screen is disabled.");
+            pw.println("");
+            pw.println("  set-disabled [--old <CREDENTIAL>] [--user USER_ID] <true|false>");
+            pw.println("    When true, disables lock screen.");
+            pw.println("");
+            pw.println("  set-pattern [--old <CREDENTIAL>] [--user USER_ID] <PATTERN>");
+            pw.println("    Sets the lock screen as pattern, using the given PATTERN to unlock.");
+            pw.println("");
+            pw.println("  set-pin [--old <CREDENTIAL>] [--user USER_ID] <PIN>");
+            pw.println("    Sets the lock screen as PIN, using the given PIN to unlock.");
+            pw.println("");
+            pw.println("  set-pin [--old <CREDENTIAL>] [--user USER_ID] <PASSWORD>");
+            pw.println("    Sets the lock screen as password, using the given PASSOWRD to unlock.");
+            pw.println("");
+            pw.println("  sp [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Gets whether synthetic password is enabled.");
+            pw.println("");
+            pw.println("  sp [--old <CREDENTIAL>] [--user USER_ID] <1|0>");
+            pw.println("    Enables / disables synthetic password.");
+            pw.println("");
+            pw.println("  clear [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Clears the lock credentials.");
+            pw.println("");
+            pw.println("  verify [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Verifies the lock credentials.");
+            pw.println("");
+        }
     }
 
     private void parseArgs() {
@@ -134,27 +176,27 @@
                 mLockPatternUtils.isSyntheticPasswordEnabled()));
     }
 
-    private void runSetPattern() throws RemoteException {
+    private void runSetPattern() {
         mLockPatternUtils.saveLockPattern(stringToPattern(mNew), mOld, mCurrentUserId);
         getOutPrintWriter().println("Pattern set to '" + mNew + "'");
     }
 
-    private void runSetPassword() throws RemoteException {
+    private void runSetPassword() {
         mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_ALPHABETIC, mCurrentUserId);
         getOutPrintWriter().println("Password set to '" + mNew + "'");
     }
 
-    private void runSetPin() throws RemoteException {
+    private void runSetPin() {
         mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_NUMERIC, mCurrentUserId);
         getOutPrintWriter().println("Pin set to '" + mNew + "'");
     }
 
-    private void runClear() throws RemoteException {
+    private void runClear() {
         mLockPatternUtils.clearLock(mOld, mCurrentUserId);
         getOutPrintWriter().println("Lock credential cleared");
     }
 
-    private void runSetDisabled() throws RemoteException {
+    private void runSetDisabled() {
         final boolean disabled = Boolean.parseBoolean(mNew);
         mLockPatternUtils.setLockScreenDisabled(disabled, mCurrentUserId);
         getOutPrintWriter().println("Lock screen disabled set to " + disabled);
@@ -165,7 +207,7 @@
         getOutPrintWriter().println(isLockScreenDisabled);
     }
 
-    private boolean checkCredential() throws RemoteException {
+    private boolean checkCredential() {
         final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
         final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
         if (havePassword || havePattern) {
diff --git a/services/robotests/src/android/app/backup/ForwardingBackupAgent.java b/services/robotests/src/android/app/backup/ForwardingBackupAgent.java
new file mode 100644
index 0000000..4ff5b7c
--- /dev/null
+++ b/services/robotests/src/android/app/backup/ForwardingBackupAgent.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.backup;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Useful for spying in {@link BackupAgent} instances since their {@link BackupAgent#onBind()} is
+ * final and always points to the original instance, instead of the spy.
+ *
+ * <p>To use, construct a spy of the desired {@link BackupAgent}, spying on the methods of interest.
+ * Then, where you need to pass the agent, use {@link ForwardingBackupAgent#forward(BackupAgent)}
+ * with the spy.
+ */
+public class ForwardingBackupAgent extends BackupAgent {
+    /** Returns a {@link BackupAgent} that forwards method calls to {@code backupAgent}. */
+    public static BackupAgent forward(BackupAgent backupAgent) {
+        return new ForwardingBackupAgent(backupAgent);
+    }
+
+    private final BackupAgent mBackupAgent;
+
+    private ForwardingBackupAgent(BackupAgent backupAgent) {
+        mBackupAgent = backupAgent;
+    }
+
+    @Override
+    public void onCreate() {
+        mBackupAgent.onCreate();
+    }
+
+    @Override
+    public void onDestroy() {
+        mBackupAgent.onDestroy();
+    }
+
+    @Override
+    public void onBackup(
+            ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)
+            throws IOException {
+        mBackupAgent.onBackup(oldState, data, newState);
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        mBackupAgent.onRestore(data, appVersionCode, newState);
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, long appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        mBackupAgent.onRestore(data, appVersionCode, newState);
+    }
+
+    @Override
+    public void onFullBackup(FullBackupDataOutput data) throws IOException {
+        mBackupAgent.onFullBackup(data);
+    }
+
+    @Override
+    public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
+        mBackupAgent.onQuotaExceeded(backupDataBytes, quotaBytes);
+    }
+
+    @Override
+    public void onRestoreFile(
+            ParcelFileDescriptor data, long size, File destination, int type, long mode, long mtime)
+            throws IOException {
+        mBackupAgent.onRestoreFile(data, size, destination, type, mode, mtime);
+    }
+
+    @Override
+    protected void onRestoreFile(
+            ParcelFileDescriptor data,
+            long size,
+            int type,
+            String domain,
+            String path,
+            long mode,
+            long mtime)
+            throws IOException {
+        mBackupAgent.onRestoreFile(data, size, type, domain, path, mode, mtime);
+    }
+
+    @Override
+    public void onRestoreFinished() {
+        mBackupAgent.onRestoreFinished();
+    }
+
+    @Override
+    public void attach(Context context) {
+        mBackupAgent.attach(context);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index d16bc26..abaed7c 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.backup;
 
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startSilentBackupThread;
 import static com.android.server.backup.testing.TransportData.backupTransport;
 import static com.android.server.backup.testing.TransportData.d2dTransport;
 import static com.android.server.backup.testing.TransportData.localTransport;
@@ -46,6 +46,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import com.android.server.backup.internal.BackupRequest;
+import com.android.server.backup.testing.BackupManagerServiceTestUtils;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportNotRegisteredException;
@@ -68,7 +69,6 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implements;
 import org.robolectric.shadows.ShadowContextWrapper;
-import org.robolectric.shadows.ShadowLog;
 import org.robolectric.shadows.ShadowLooper;
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowSettings;
@@ -104,7 +104,10 @@
         mTransport = backupTransport();
         mTransportName = mTransport.transportName;
 
-        mBackupThread = startBackupThread(this::uncaughtException);
+        // Unrelated exceptions are thrown in the backup thread. Until we mock everything properly
+        // we should not fail tests because of this. This is not flakiness, the exceptions thrown
+        // don't interfere with the tests.
+        mBackupThread = startSilentBackupThread(TAG);
         mShadowBackupLooper = shadowOf(mBackupThread.getLooper());
 
         ContextWrapper context = RuntimeEnvironment.application;
@@ -113,8 +116,10 @@
         mShadowContext = shadowOf(context);
 
         File cacheDir = mContext.getCacheDir();
-        mBaseStateDir = new File(cacheDir, "base_state_dir");
-        mDataDir = new File(cacheDir, "data_dir");
+        // Corresponds to /data/backup
+        mBaseStateDir = new File(cacheDir, "base_state");
+        // Corresponds to /cache/backup_stage
+        mDataDir = new File(cacheDir, "data");
 
         ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
     }
@@ -126,13 +131,6 @@
         ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
     }
 
-    private void uncaughtException(Thread thread, Throwable e) {
-        // Unrelated exceptions are thrown in the backup thread. Until we mock everything properly
-        // we should not fail tests because of this. This is not flakiness, the exceptions thrown
-        // don't interfere with the tests.
-        ShadowLog.e(TAG, "Uncaught exception in test thread " + thread.getName(), e);
-    }
-
     /* Tests for destination string */
 
     @Test
@@ -864,22 +862,8 @@
     }
 
     private BackupManagerService createInitializedBackupManagerService() {
-        BackupManagerService backupManagerService =
-                new BackupManagerService(
-                        mContext,
-                        new Trampoline(mContext),
-                        mBackupThread,
-                        mBaseStateDir,
-                        mDataDir,
-                        mTransportManager);
-        mShadowBackupLooper.runToEndOfTasks();
-        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
-        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
-        // specific time to the looper the time of those messages will be before the looper's time.
-        // To fix this we advance SystemClock as well since that is from where the handlers read
-        // time.
-        ShadowSystemClock.setCurrentTimeMillis(mShadowBackupLooper.getScheduler().getCurrentTime());
-        return backupManagerService;
+        return BackupManagerServiceTestUtils.createInitializedBackupManagerService(
+                mContext, mBackupThread, mBaseStateDir, mDataDir, mTransportManager);
     }
 
     private void setUpPowerManager(BackupManagerService backupManagerService) {
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index 88a51a5..2d6dd4d 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -16,12 +16,17 @@
 
 package com.android.server.backup;
 
+import static android.app.backup.ForwardingBackupAgent.forward;
+
+import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createInitializedBackupManagerService;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
 import static com.android.server.backup.testing.TestUtils.uncheck;
 import static com.android.server.backup.testing.TransportData.backupTransport;
 import static com.google.common.truth.Truth.assertThat;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import static java.util.Collections.emptyList;
 import static java.util.stream.Collectors.toCollection;
 import static java.util.stream.Collectors.toList;
@@ -34,6 +39,7 @@
 import static org.mockito.ArgumentMatchers.intThat;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -51,12 +57,12 @@
 import android.app.backup.IBackupManager;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.DeadObjectException;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
@@ -77,13 +83,23 @@
 import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
+
+import com.google.common.truth.IterableSubject;
+
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Stream;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -98,6 +114,19 @@
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowQueuedWork;
 
+// TODO: Don't do backup for full-backup
+// TODO: Don't do backup for stopped
+// TODO: Don't do backup for non-eligible
+// TODO: (performBackup() => SUCCESS, finishBackup() => SUCCESS) => delete stage file, renames
+// state file
+// TODO: Check agent writes state file => check file content
+// TODO: Check agent writes new state file => next agent reads it correctly
+// TODO: Check non-incremental has empty state file
+// TODO: Check queue of 2, transport rejecting package but other package proceeds
+// TODO: Check queue in general, behavior w/ multiple packages
+// TODO: Check quota is passed from transport to agent
+// TODO: Check non-incremental and transport requests PM in queue
+// TODO: Verify initialization
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
         manifest = Config.NONE,
@@ -114,20 +143,22 @@
     private static final String PACKAGE_1 = "com.example.package1";
     private static final String PACKAGE_2 = "com.example.package2";
 
-    @Mock private BackupManagerService mBackupManagerService;
     @Mock private TransportManager mTransportManager;
     @Mock private DataChangedJournal mDataChangedJournal;
     @Mock private IBackupObserver mObserver;
     @Mock private IBackupManagerMonitor mMonitor;
     @Mock private OnTaskFinishedListener mListener;
+    private BackupManagerService mBackupManagerService;
     private TransportData mTransport;
     private ShadowLooper mShadowBackupLooper;
-    private BackupHandler mBackupHandler;
+    private Handler mBackupHandler;
     private PowerManager.WakeLock mWakeLock;
     private ShadowPackageManager mShadowPackageManager;
     private FakeIBackupManager mBackupManager;
     private File mBaseStateDir;
+    private File mDataDir;
     private Application mApplication;
+    private Context mContext;
 
     @Before
     public void setUp() throws Exception {
@@ -136,49 +167,269 @@
         mTransport = backupTransport();
 
         mApplication = RuntimeEnvironment.application;
+        mContext = mApplication;
+
         File cacheDir = mApplication.getCacheDir();
-        mBaseStateDir = new File(cacheDir, "base_state_dir");
-        File dataDir = new File(cacheDir, "data_dir");
-        assertThat(mBaseStateDir.mkdir()).isTrue();
-        assertThat(dataDir.mkdir()).isTrue();
+        // Corresponds to /data/backup
+        mBaseStateDir = new File(cacheDir, "base_state");
+        // Corresponds to /cache/backup_stage
+        mDataDir = new File(cacheDir, "data");
+        // We create here simulating init.rc
+        mDataDir.mkdirs();
+        assertThat(mDataDir.isDirectory()).isTrue();
 
         PackageManager packageManager = mApplication.getPackageManager();
         mShadowPackageManager = shadowOf(packageManager);
 
         mWakeLock = createBackupWakeLock(mApplication);
 
-        Looper backupLooper = startBackupThreadAndGetLooper();
-        mShadowBackupLooper = shadowOf(backupLooper);
-
-        Handler mainHandler = new Handler(Looper.getMainLooper());
-        BackupAgentTimeoutParameters agentTimeoutParameters =
-                new BackupAgentTimeoutParameters(mainHandler, mApplication.getContentResolver());
-        agentTimeoutParameters.start();
-
-        // We need to mock BMS timeout parameters before initializing the BackupHandler since
-        // the constructor of BackupHandler relies on the timeout parameters.
-        when(mBackupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
-        mBackupHandler = new BackupHandler(mBackupManagerService, backupLooper);
-
         mBackupManager = spy(FakeIBackupManager.class);
 
-        BackupManagerConstants constants =
-                new BackupManagerConstants(mainHandler, mApplication.getContentResolver());
-        constants.start();
-
+        mBackupManagerService =
+                spy(
+                        createInitializedBackupManagerService(
+                                mContext, mBaseStateDir, mDataDir, mTransportManager));
         setUpBackupManagerServiceBasics(
                 mBackupManagerService,
                 mApplication,
                 mTransportManager,
                 packageManager,
-                mBackupHandler,
+                mBackupManagerService.getBackupHandler(),
                 mWakeLock,
-                agentTimeoutParameters);
+                mBackupManagerService.getAgentTimeoutParameters());
         when(mBackupManagerService.getBaseStateDir()).thenReturn(mBaseStateDir);
-        when(mBackupManagerService.getDataDir()).thenReturn(dataDir);
+        when(mBackupManagerService.getDataDir()).thenReturn(mDataDir);
         when(mBackupManagerService.getBackupManagerBinder()).thenReturn(mBackupManager);
-        when(mBackupManagerService.getConstants()).thenReturn(constants);
-        when(mBackupManagerService.makeMetadataAgent()).thenAnswer(invocation -> createPmAgent());
+
+        mBackupHandler = mBackupManagerService.getBackupHandler();
+        mShadowBackupLooper = shadowOf(mBackupHandler.getLooper());
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty() throws Exception {
+        when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
+        TransportMock transportMock = setUpTransport(mTransport);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getPendingInits()).isEmpty();
+        assertThat(mBackupManagerService.isBackupRunning()).isFalse();
+        assertThat(mBackupManagerService.getCurrentOperations().size()).isEqualTo(0);
+        assertThat(mWakeLock.isHeld()).isFalse();
+        assertDirectory(getStateDirectory(mTransport)).isEmpty();
+        assertDirectory(mDataDir.toPath()).isEmpty();
+        verify(transportMock.transport, never()).initializeDevice();
+        verify(transportMock.transport, never()).performBackup(any(), any(), anyInt());
+        verify(transportMock.transport, never()).finishBackup();
+        verify(mDataChangedJournal).delete();
+        verify(mListener).onFinished(any());
+        verify(mObserver, never()).onResult(any(), anyInt());
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+        // TODO: Verify set current token?
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty_doesNotChangeStateFiles() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+        createPmStateFile();
+        Files.write(getStateFile(mTransport, PACKAGE_1), "packageState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_MANAGER_SENTINEL))).isEqualTo("pmState".getBytes());
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1))).isEqualTo("packageState".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackage_aboutAgent() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(agentMock.agent).onBackup(any(), any(), any());
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("newState".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackage_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).logBackupComplete(PACKAGE_1);
+        verify(mObserver).onResult(PACKAGE_1, BackupManager.SUCCESS);
+        verify(mListener).onFinished(any());
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackage_releasesWakeLock() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mWakeLock.isHeld()).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackage_updatesBookkeeping() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getPendingInits()).isEmpty();
+        assertThat(mBackupManagerService.isBackupRunning()).isFalse();
+        assertThat(mBackupManagerService.getCurrentOperations().size()).isEqualTo(0);
+        verify(mDataChangedJournal).delete();
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackageIncremental_passesOldStateToAgent() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        false,
+                        PACKAGE_1);
+        createPmStateFile();
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(agentMock.oldState).isEqualTo("oldState".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackageNonIncremental_passesEmptyOldStateToAgent() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        true,
+                        PACKAGE_1);
+        createPmStateFile();
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(agentMock.oldState).isEqualTo(new byte[0]);
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackageNonIncremental_doesNotBackUpPm() throws Exception {
+        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        true,
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(pmAgent, never()).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenPackageAndPmNonIncremental_backsUpPm() throws Exception {
+        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        true,
+                        PACKAGE_1,
+                        PACKAGE_MANAGER_SENTINEL);
+
+        runTask(task);
+
+        verify(pmAgent).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackageIncremental_backsUpPm() throws Exception {
+        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        false,
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(pmAgent).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackageNoPmState_initializesTransport() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.deleteIfExists(getStateFile(mTransport, PACKAGE_MANAGER_SENTINEL));
+
+        runTask(task);
+
+        verify(transportMock.transport).initializeDevice();
+    }
+
+    @Test
+    public void testRunTask_whenSinglePackageWithPmState_doesNotInitializeTransport()
+            throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PerformBackupTask task =
+                createPerformBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        createPmStateFile();
+
+        runTask(task);
+
+        verify(transportMock.transport, never()).initializeDevice();
     }
 
     @Test
@@ -249,20 +500,6 @@
     }
 
     @Test
-    public void testRunTask_callsListenerAndObserver() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        setUpAgent(PACKAGE_1);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(mListener).onFinished(any());
-        verify(mObserver).backupFinished(eq(BackupManager.SUCCESS));
-    }
-
-    @Test
     public void testRunTask_releasesWakeLock() throws Exception {
         TransportMock transportMock = setUpTransport(mTransport);
         setUpAgent(PACKAGE_1);
@@ -281,7 +518,7 @@
         IBackupTransport transportBinder = transportMock.transport;
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         agentOnBackupDo(
-                agentMock.agent,
+                agentMock,
                 (oldState, dataOutput, newState) -> {
                     writeData(dataOutput, "key1", "foo".getBytes());
                     writeData(dataOutput, "key2", "bar".getBytes());
@@ -289,43 +526,48 @@
         PerformBackupTask task =
                 createPerformBackupTask(
                         transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-        // We need to verify at call time because the file is deleted right after
+        Path backupDataPath =
+                Files.createTempFile(mContext.getCacheDir().toPath(), "backup", ".tmp");
         when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .then(this::mockAndVerifyTransportPerformBackupData);
+                .then(
+                        invocation -> {
+                            ParcelFileDescriptor backupDataParcelFd = invocation.getArgument(1);
+                            FileDescriptor backupDataFd = backupDataParcelFd.getFileDescriptor();
+                            Files.copy(
+                                    new FileInputStream(backupDataFd),
+                                    backupDataPath,
+                                    REPLACE_EXISTING);
+                            backupDataParcelFd.close();
+                            return BackupTransport.TRANSPORT_OK;
+                        });
 
         runTask(task);
 
-        // Already verified data in mockAndVerifyPerformBackupData
         verify(transportBinder).performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
-    }
 
-    private int mockAndVerifyTransportPerformBackupData(InvocationOnMock invocation)
-            throws IOException {
-        ParcelFileDescriptor data = invocation.getArgument(1);
-
-        // Verifying that what we passed to the transport is what the agent wrote
-        BackupDataInput dataInput = new BackupDataInput(data.getFileDescriptor());
+        // Now verify data sent
+        FileInputStream inputStream = new FileInputStream(backupDataPath.toFile());
+        BackupDataInput backupData = new BackupDataInput(inputStream.getFD());
 
         // "key1" => "foo"
-        assertThat(dataInput.readNextHeader()).isTrue();
-        assertThat(dataInput.getKey()).isEqualTo("key1");
-        int size1 = dataInput.getDataSize();
+        assertThat(backupData.readNextHeader()).isTrue();
+        assertThat(backupData.getKey()).isEqualTo("key1");
+        int size1 = backupData.getDataSize();
         byte[] data1 = new byte[size1];
-        dataInput.readEntityData(data1, 0, size1);
+        backupData.readEntityData(data1, 0, size1);
         assertThat(data1).isEqualTo("foo".getBytes());
 
         // "key2" => "bar"
-        assertThat(dataInput.readNextHeader()).isTrue();
-        assertThat(dataInput.getKey()).isEqualTo("key2");
-        int size2 = dataInput.getDataSize();
+        assertThat(backupData.readNextHeader()).isTrue();
+        assertThat(backupData.getKey()).isEqualTo("key2");
+        int size2 = backupData.getDataSize();
         byte[] data2 = new byte[size2];
-        dataInput.readEntityData(data2, 0, size2);
+        backupData.readEntityData(data2, 0, size2);
         assertThat(data2).isEqualTo("bar".getBytes());
 
         // No more
-        assertThat(dataInput.readNextHeader()).isFalse();
-
-        return BackupTransport.TRANSPORT_OK;
+        assertThat(backupData.readNextHeader()).isFalse();
+        inputStream.close();
     }
 
     @Test
@@ -350,7 +592,7 @@
         TransportMock transportMock = setUpTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         agentOnBackupDo(
-                agentMock.agent,
+                agentMock,
                 (oldState, dataOutput, newState) -> {
                     char prohibitedChar = 0xff00;
                     writeData(dataOutput, prohibitedChar + "key", "foo".getBytes());
@@ -374,13 +616,13 @@
         AgentMock agentMock1 = agentMocks.get(0);
         AgentMock agentMock2 = agentMocks.get(1);
         agentOnBackupDo(
-                agentMock1.agent,
+                agentMock1,
                 (oldState, dataOutput, newState) -> {
                     char prohibitedChar = 0xff00;
                     writeData(dataOutput, prohibitedChar + "key", "foo".getBytes());
                 });
         agentOnBackupDo(
-                agentMock2.agent,
+                agentMock2,
                 (oldState, dataOutput, newState) -> {
                     writeData(dataOutput, "key", "bar".getBytes());
                 });
@@ -528,6 +770,7 @@
 
         runTask(task);
 
+        // Error because it was non-incremental already, so transport can't request it
         verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_ABORTED);
         verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
     }
@@ -553,10 +796,9 @@
                         mTransport.transportDirName,
                         false,
                         PACKAGE_1);
-        // Write content to be incremental
-        Files.write(
-                Paths.get(mBaseStateDir.getAbsolutePath(), mTransport.transportDirName, PACKAGE_1),
-                "existent".getBytes());
+        createPmStateFile();
+        // Write state to be incremental
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
 
         runTask(task);
 
@@ -566,25 +808,12 @@
     }
 
     @Test
-    public void testRunTask_whenQueueEmpty() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, true);
-
-        runTask(task);
-
-        verify(mObserver).backupFinished(eq(BackupManager.SUCCESS));
-    }
-
-    @Test
     public void testRunTask_whenIncrementalAndTransportUnavailableDuringPmBackup()
             throws Exception {
         TransportMock transportMock = setUpTransport(mTransport);
         IBackupTransport transportBinder = transportMock.transport;
         setUpAgent(PACKAGE_1);
-        when(transportBinder.getBackupQuota(
-                        eq(BackupManagerService.PACKAGE_MANAGER_SENTINEL), anyBoolean()))
+        when(transportBinder.getBackupQuota(eq(PACKAGE_MANAGER_SENTINEL), anyBoolean()))
                 .thenThrow(DeadObjectException.class);
         PerformBackupTask task =
                 createPerformBackupTask(
@@ -600,9 +829,10 @@
     }
 
     @Test
-    public void testRunTask_whenIncrementalAndAgentFails() throws Exception {
+    public void testRunTask_whenIncrementalAndPmAgentFails() throws Exception {
         TransportMock transportMock = setUpTransport(mTransport);
-        createFakePmAgent();
+        PackageManagerBackupAgent pmAgent = createThrowingPmAgent();
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
         PerformBackupTask task =
                 createPerformBackupTask(
                         transportMock.transportClient,
@@ -627,11 +857,18 @@
     private TransportMock setUpTransport(TransportData transport) throws Exception {
         TransportMock transportMock =
                 TransportTestUtils.setUpTransport(mTransportManager, transport);
-        File stateDir = new File(mBaseStateDir, transport.transportDirName);
-        assertThat(stateDir.mkdir()).isTrue();
+        Files.createDirectories(getStateDirectory(transport));
         return transportMock;
     }
 
+    private Path getStateDirectory(TransportData transport) {
+        return mBaseStateDir.toPath().resolve(transport.transportDirName);
+    }
+
+    private Path getStateFile(TransportData transport, String packageName) {
+        return getStateDirectory(transport).resolve(packageName);
+    }
+
     private List<AgentMock> setUpAgents(String... packageNames) {
         return Stream.of(packageNames).map(this::setUpAgent).collect(toList());
     }
@@ -652,9 +889,9 @@
                     spy(IBackupAgent.Stub.asInterface(backupAgent.onBind()));
             // Don't crash our only process (in production code this would crash the app, not us)
             doNothing().when(backupAgentBinder).fail(any());
-            when(mBackupManagerService.bindToAgentSynchronous(
-                            eq(packageInfo.applicationInfo), anyInt()))
-                    .thenReturn(backupAgentBinder);
+            doReturn(backupAgentBinder)
+                    .when(mBackupManagerService)
+                    .bindToAgentSynchronous(eq(packageInfo.applicationInfo), anyInt());
             return new AgentMock(backupAgentBinder, backupAgent);
         } catch (RemoteException e) {
             // Never happens, compiler happy
@@ -668,12 +905,15 @@
 
     private AgentMock setUpAgentWithData(String packageName) {
         AgentMock agentMock = setUpAgent(packageName);
+
         uncheck(
                 () ->
                         agentOnBackupDo(
-                                agentMock.agent,
-                                (oldState, dataOutput, newState) ->
-                                        writeData(dataOutput, "key", packageName.getBytes())));
+                                agentMock,
+                                (oldState, dataOutput, newState) -> {
+                                    writeData(dataOutput, "key", ("data" + packageName).getBytes());
+                                    writeState(newState, ("state" + packageName).getBytes());
+                                }));
         return agentMock;
     }
 
@@ -719,13 +959,12 @@
      * Returns an implementation of PackageManagerBackupAgent that throws RuntimeException in {@link
      * BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
      */
-    private PackageManagerBackupAgent createFakePmAgent() {
-        PackageManagerBackupAgent fakePmAgent =
-                new FakePackageManagerBackupAgent(mApplication.getPackageManager());
-        fakePmAgent.attach(mApplication);
-        fakePmAgent.onCreate();
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(fakePmAgent);
-        return fakePmAgent;
+    private PackageManagerBackupAgent createThrowingPmAgent() {
+        PackageManagerBackupAgent pmAgent =
+                new ThrowingPackageManagerBackupAgent(mApplication.getPackageManager());
+        pmAgent.attach(mApplication);
+        pmAgent.onCreate();
+        return pmAgent;
     }
 
     /** Matches {@link PackageInfo} whose package name is {@code packageName}. */
@@ -751,9 +990,49 @@
         dataOutput.writeEntityData(data, data.length);
     }
 
-    private static void agentOnBackupDo(BackupAgent agent, BackupAgentOnBackup function)
+    private static void writeState(ParcelFileDescriptor newState, byte[] state) throws IOException {
+        OutputStream outputStream = new FileOutputStream(newState.getFileDescriptor());
+        outputStream.write(state);
+        outputStream.flush();
+    }
+
+    /** Prevents the states from being reset and transport initialization. */
+    private void createPmStateFile() throws IOException {
+        Files.write(getStateFile(mTransport, PACKAGE_MANAGER_SENTINEL), "pmState".getBytes());
+    }
+
+    /**
+     * Implements {@code function} for {@link BackupAgent#onBackup(ParcelFileDescriptor,
+     * BackupDataOutput, ParcelFileDescriptor)} of {@code agentMock} and populates {@link
+     * AgentMock#oldState}.
+     */
+    private static void agentOnBackupDo(AgentMock agentMock, BackupAgentOnBackup function)
             throws Exception {
-        doAnswer(function).when(agent).onBackup(any(), any(), any());
+        doAnswer(
+                        (BackupAgentOnBackup)
+                                (oldState, dataOutput, newState) -> {
+                                    ByteArrayOutputStream outputStream =
+                                            new ByteArrayOutputStream();
+                                    Utils.transferStreamedData(
+                                            new FileInputStream(oldState.getFileDescriptor()),
+                                            outputStream);
+                                    agentMock.oldState = outputStream.toByteArray();
+                                    function.onBackup(oldState, dataOutput, newState);
+                                })
+                .when(agentMock.agent)
+                .onBackup(any(), any(), any());
+    }
+
+    // TODO: Find some implementation? Extract?
+    private static <T> Iterable<T> oneTimeIterable(Iterator<T> iterator) {
+        return () -> iterator;
+    }
+
+    private static IterableSubject<
+                    ? extends IterableSubject<?, Path, Iterable<Path>>, Path, Iterable<Path>>
+            assertDirectory(Path directory) throws IOException {
+        return assertThat(oneTimeIterable(Files.newDirectoryStream(directory).iterator()))
+                .named("directory " + directory);
     }
 
     @FunctionalInterface
@@ -777,6 +1056,7 @@
     private static class AgentMock {
         private final IBackupAgent agentBinder;
         private final BackupAgent agent;
+        private byte[] oldState;
 
         private AgentMock(IBackupAgent agentBinder, BackupAgent agent) {
             this.agentBinder = agentBinder;
@@ -805,8 +1085,8 @@
         }
     }
 
-    private static class FakePackageManagerBackupAgent extends PackageManagerBackupAgent {
-        public FakePackageManagerBackupAgent(PackageManager packageMgr) {
+    private static class ThrowingPackageManagerBackupAgent extends PackageManagerBackupAgent {
+        ThrowingPackageManagerBackupAgent(PackageManager packageMgr) {
             super(packageMgr);
         }
 
diff --git a/services/robotests/src/com/android/server/backup/Utils.java b/services/robotests/src/com/android/server/backup/Utils.java
new file mode 100644
index 0000000..7cdca17
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/Utils.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class Utils {
+    public static final int BUFFER_SIZE = 8192;
+
+    public static void transferStreamedData(InputStream in, OutputStream out) throws IOException {
+        transferStreamedData(in, out, BUFFER_SIZE);
+    }
+
+    public static void transferStreamedData(InputStream in, OutputStream out, int bufferSize)
+            throws IOException {
+        byte[] buffer = new byte[bufferSize];
+        int read;
+        while ((read = in.read(buffer)) != -1) {
+            out.write(buffer, 0, read);
+        }
+    }
+
+    private Utils() {}
+}
diff --git a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index 92d6bbd..c51b75b 100644
--- a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -77,10 +77,9 @@
 
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
-    manifest = Config.NONE,
-    sdk = 26,
-    shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class}
-)
+        manifest = Config.NONE,
+        sdk = 26,
+        shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
 @SystemLoaderPackages({"com.android.server.backup"})
 @Presubmit
 public class ActiveRestoreSessionTest {
@@ -130,6 +129,7 @@
 
         mWakeLock = createBackupWakeLock(application);
 
+        // TODO: Migrate to use spy(createInitializedBackupManagerService())
         setUpBackupManagerServiceBasics(
                 mBackupManagerService,
                 application,
diff --git a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
index 5a886e3..522578f 100644
--- a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -16,13 +16,20 @@
 
 package com.android.server.backup.testing;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
 
+import android.annotation.Nullable;
 import android.app.Application;
 import android.app.IActivityManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.PowerManager;
@@ -30,32 +37,118 @@
 
 import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.Trampoline;
 import com.android.server.backup.TransportManager;
-import com.android.server.backup.internal.BackupHandler;
+import com.android.server.backup.internal.Operation;
 
+import org.mockito.stubbing.Answer;
+import org.robolectric.shadows.ShadowLog;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowSystemClock;
+
+import java.io.File;
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.concurrent.atomic.AtomicReference;
 
 /** Test utils for {@link BackupManagerService} and friends. */
 public class BackupManagerServiceTestUtils {
-    /** Sets up basic mocks for {@link BackupManagerService}. */
+    public static BackupManagerService createInitializedBackupManagerService(
+            Context context, File baseStateDir, File dataDir, TransportManager transportManager) {
+        return createInitializedBackupManagerService(
+                context,
+                startBackupThread(null),
+                baseStateDir,
+                dataDir,
+                transportManager);
+    }
+
+    public static BackupManagerService createInitializedBackupManagerService(
+            Context context,
+            HandlerThread backupThread,
+            File baseStateDir,
+            File dataDir,
+            TransportManager transportManager) {
+        BackupManagerService backupManagerService =
+                new BackupManagerService(
+                        context,
+                        new Trampoline(context),
+                        backupThread,
+                        baseStateDir,
+                        dataDir,
+                        transportManager);
+        ShadowLooper shadowBackupLooper = shadowOf(backupThread.getLooper());
+        shadowBackupLooper.runToEndOfTasks();
+        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
+        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
+        // specific time to the looper the time of those messages will be before the looper's time.
+        // To fix this we advance SystemClock as well since that is from where the handlers read
+        // time.
+        ShadowSystemClock.setCurrentTimeMillis(shadowBackupLooper.getScheduler().getCurrentTime());
+        return backupManagerService;
+    }
+
+    /** Sets up basic mocks for {@link BackupManagerService} mock. */
+    @SuppressWarnings("ResultOfMethodCallIgnored")
     public static void setUpBackupManagerServiceBasics(
             BackupManagerService backupManagerService,
             Context context,
             TransportManager transportManager,
             PackageManager packageManager,
-            BackupHandler backupHandler,
+            Handler backupHandler,
             PowerManager.WakeLock wakeLock,
             BackupAgentTimeoutParameters agentTimeoutParameters) {
+        SparseArray<Operation> operations = new SparseArray<>();
+
         when(backupManagerService.getContext()).thenReturn(context);
         when(backupManagerService.getTransportManager()).thenReturn(transportManager);
         when(backupManagerService.getPackageManager()).thenReturn(packageManager);
         when(backupManagerService.getBackupHandler()).thenReturn(backupHandler);
         when(backupManagerService.getCurrentOpLock()).thenReturn(new Object());
         when(backupManagerService.getQueueLock()).thenReturn(new Object());
-        when(backupManagerService.getCurrentOperations()).thenReturn(new SparseArray<>());
+        when(backupManagerService.getCurrentOperations()).thenReturn(operations);
         when(backupManagerService.getActivityManager()).thenReturn(mock(IActivityManager.class));
         when(backupManagerService.getWakelock()).thenReturn(wakeLock);
         when(backupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
+
+        AccessorMock backupEnabled = mockAccessor(false);
+        doAnswer(backupEnabled.getter).when(backupManagerService).isBackupEnabled();
+        doAnswer(backupEnabled.setter).when(backupManagerService).setBackupEnabled(anyBoolean());
+
+        AccessorMock backupRunning = mockAccessor(false);
+        doAnswer(backupEnabled.getter).when(backupManagerService).isBackupRunning();
+        doAnswer(backupRunning.setter).when(backupManagerService).setBackupRunning(anyBoolean());
+
+        doAnswer(
+                        invocation -> {
+                            operations.put(invocation.getArgument(0), invocation.getArgument(1));
+                            return null;
+                        })
+                .when(backupManagerService)
+                .putOperation(anyInt(), any());
+        doAnswer(
+                        invocation -> {
+                            int token = invocation.getArgument(0);
+                            operations.remove(token);
+                            return null;
+                        })
+                .when(backupManagerService)
+                .removeOperation(anyInt());
+    }
+
+    /**
+     * Returns one getter {@link Answer<T>} and one setter {@link Answer<T>} to be easily passed to
+     * Mockito mocking facilities.
+     *
+     * @param defaultValue Value returned by the getter if there was no setter call until then.
+     */
+    public static <T> AccessorMock<T> mockAccessor(T defaultValue) {
+        AtomicReference<T> holder = new AtomicReference<>(defaultValue);
+        return new AccessorMock<>(
+                invocation -> holder.get(),
+                invocation -> {
+                    holder.set(invocation.getArgument(0));
+                    return null;
+                });
     }
 
     public static PowerManager.WakeLock createBackupWakeLock(Application application) {
@@ -88,12 +181,38 @@
      * @return The backup thread.
      * @see #startBackupThreadAndGetLooper()
      */
-    public static HandlerThread startBackupThread(UncaughtExceptionHandler exceptionHandler) {
+    public static HandlerThread startBackupThread(
+            @Nullable UncaughtExceptionHandler exceptionHandler) {
         HandlerThread backupThread = new HandlerThread("backup");
         backupThread.setUncaughtExceptionHandler(exceptionHandler);
         backupThread.start();
         return backupThread;
     }
 
+    /**
+     * Similar to {@link #startBackupThread(UncaughtExceptionHandler)} but logging uncaught
+     * exceptions to logcat.
+     *
+     * @param tag Tag used for logging exceptions.
+     * @return The backup thread.
+     * @see #startBackupThread(UncaughtExceptionHandler)
+     */
+    public static HandlerThread startSilentBackupThread(String tag) {
+        return startBackupThread(
+                (thread, e) ->
+                        ShadowLog.e(
+                                tag, "Uncaught exception in test thread " + thread.getName(), e));
+    }
+
     private BackupManagerServiceTestUtils() {}
+
+    public static class AccessorMock<T> {
+        public Answer<T> getter;
+        public Answer<T> setter;
+
+        private AccessorMock(Answer<T> getter, Answer<T> setter) {
+            this.getter = getter;
+            this.setter = setter;
+        }
+    }
 }
diff --git a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
index 5844131..6625443 100644
--- a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
@@ -26,13 +26,13 @@
 
 import static java.util.stream.Collectors.toList;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.os.RemoteException;
-import android.support.annotation.IntDef;
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.TransportManager;
@@ -42,6 +42,8 @@
 
 import org.robolectric.shadows.ShadowPackageManager;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.stream.Stream;
 
@@ -209,6 +211,7 @@
         TransportStatus.REGISTERED_UNAVAILABLE,
         TransportStatus.UNREGISTERED
     })
+    @Retention(RetentionPolicy.SOURCE)
     public @interface TransportStatus {
         int REGISTERED_AVAILABLE = 0;
         int REGISTERED_UNAVAILABLE = 1;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index 424c08c..2214d74 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -80,7 +80,7 @@
         MockitoAnnotations.initMocks(this);
         final Context context = InstrumentationRegistry.getTargetContext();
         mUserId = ActivityManager.getCurrentUser();
-        mCommand = new LockSettingsShellCommand(context, mLockPatternUtils);
+        mCommand = new LockSettingsShellCommand(mLockPatternUtils);
     }
 
     @Test
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 35f64a1..dd1ddfa 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -924,8 +924,7 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
-            final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
-                    PackageManager.MATCH_ANY_USER, userId);
+            final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
             // If the calling app is asking about itself, continue, else check for permission.
             if (packageUid != callingUid) {
                 if (!hasPermission(callingPackage)) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 4efe0b5..7d38e82 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -64,6 +64,9 @@
     private String mLastBackgroundedPackage;
     private final int mUserId;
 
+    // STOPSHIP: Temporary member variable for debugging b/110930764.
+    private UsageEvents.Event mLastEvent;
+
     private static final long[] INTERVAL_LENGTH = new long[] {
             UnixCalendar.DAY_IN_MILLIS, UnixCalendar.WEEK_IN_MILLIS,
             UnixCalendar.MONTH_IN_MILLIS, UnixCalendar.YEAR_IN_MILLIS
@@ -156,6 +159,8 @@
                     + eventToString(event.mEventType));
         }
 
+        mLastEvent = new UsageEvents.Event(event);
+
         if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
             // Need to rollover
             rolloverStats(event.mTimeStamp);
@@ -306,6 +311,36 @@
                 Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
                         + currentStats.endTime);
             }
+
+            // STOPSHIP: Temporary logging for b/110930764.
+            if (intervalType == UsageStatsManager.INTERVAL_DAILY
+                    && mLastEvent.mTimeStamp >= beginTime) {
+                final IntervalStats diskStats = mDatabase.getLatestUsageStats(
+                        UsageStatsManager.INTERVAL_DAILY);
+                StringBuilder sb = new StringBuilder(256);
+                sb.append("Last 24 hours of UsageStats missing! timeRange : ");
+                sb.append(beginTime);
+                sb.append(", ");
+                sb.append(endTime);
+                sb.append("\nLast reported Usage Event time : ");
+                sb.append(mLastEvent.mTimeStamp);
+                if (currentStats == null) {
+                    sb.append("\nNo in memory event stats available.");
+                } else {
+                    sb.append("\nLast in memory event time : ");
+                    sb.append(currentStats.endTime);
+                    sb.append("\nLast save time: ");
+                    sb.append(currentStats.lastTimeSaved);
+                }
+                if (diskStats == null) {
+                    sb.append("\nNo on disk event stats available.");
+                } else {
+                    sb.append("\nLast on disk event time : ");
+                    sb.append(diskStats.endTime);
+                }
+                Slog.wtf(TAG, sb.toString());
+            }
+
             // Nothing newer available.
             return null;
         }
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index e881549..c393155 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.AccessNetworkConstants.TransportType;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -59,15 +60,15 @@
     /** Not registered. The device is not currently searching a new operator to register */
     public static final int REG_STATE_NOT_REG_NOT_SEARCHING = 0;
     /** Registered on home network */
-    public static final int REG_STATE_HOME = 1;
+    public static final int REG_STATE_HOME                  = 1;
     /** Not registered. The device is currently searching a new operator to register */
-    public static final int REG_STATE_NOT_REG_SEARCHING = 2;
+    public static final int REG_STATE_NOT_REG_SEARCHING     = 2;
     /** Registration denied */
-    public static final int REG_STATE_DENIED = 3;
+    public static final int REG_STATE_DENIED                = 3;
     /** Registration state is unknown */
-    public static final int REG_STATE_UNKNOWN = 4;
+    public static final int REG_STATE_UNKNOWN               = 4;
     /** Registered on roaming network */
-    public static final int REG_STATE_ROAMING = 5;
+    public static final int REG_STATE_ROAMING               = 5;
 
     /**
      * Supported service type
@@ -79,16 +80,16 @@
                     SERVICE_TYPE_EMERGENCY})
     public @interface ServiceType {}
 
-    public static final int SERVICE_TYPE_VOICE = 1;
-    public static final int SERVICE_TYPE_DATA = 2;
-    public static final int SERVICE_TYPE_SMS = 3;
-    public static final int SERVICE_TYPE_VIDEO = 4;
-    public static final int SERVICE_TYPE_EMERGENCY = 5;
+    public static final int SERVICE_TYPE_VOICE      = 1;
+    public static final int SERVICE_TYPE_DATA       = 2;
+    public static final int SERVICE_TYPE_SMS        = 3;
+    public static final int SERVICE_TYPE_VIDEO      = 4;
+    public static final int SERVICE_TYPE_EMERGENCY  = 5;
 
     @Domain
     private final int mDomain;
 
-    /** {@link AccessNetworkConstants.TransportType}*/
+    /** {@link TransportType} */
     private final int mTransportType;
 
     @RegState
@@ -96,7 +97,7 @@
 
     private final int mAccessNetworkTechnology;
 
-    private final int mReasonForDenial;
+    private final int mRejectCause;
 
     private final boolean mEmergencyOnly;
 
@@ -112,22 +113,35 @@
     private DataSpecificRegistrationStates mDataSpecificStates;
 
     /**
-     * @param domain Network domain. Must be DOMAIN_CS or DOMAIN_PS.
-     * @param transportType Transport type. Must be {@link AccessNetworkConstants.TransportType}
-     * @param regState Network registration state.
-     * @param accessNetworkTechnology See TelephonyManager NETWORK_TYPE_XXXX.
-     * @param reasonForDenial Reason for denial if the registration state is DENIED.
-     * @param availableServices The supported service.
-     * @param cellIdentity The identity representing a unique cell
+     * @param domain Network domain. Must be a {@link Domain}. For {@link TransportType#WLAN}
+     * transport, this must set to {@link #DOMAIN_PS}.
+     * @param transportType Transport type. Must be one of the{@link TransportType}.
+     * @param regState Network registration state. Must be one of the {@link RegState}. For
+     * {@link TransportType#WLAN} transport, only {@link #REG_STATE_HOME} and
+     * {@link #REG_STATE_NOT_REG_NOT_SEARCHING} are valid states.
+     * @param accessNetworkTechnology Access network technology. Must be one of TelephonyManager
+     * NETWORK_TYPE_XXXX. For {@link TransportType#WLAN} transport, set to
+     * {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
+     * @param rejectCause Reason for denial if the registration state is {@link #REG_STATE_DENIED}.
+     * Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
+     * 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA. If
+     * the reject cause is not supported or unknown, set it to 0.
+     * // TODO: Add IWLAN reject cause reference
+     * @param emergencyOnly True if this registration is for emergency only.
+     * @param availableServices The list of the supported services. Each element must be one of
+     * the {@link ServiceType}.
+     * @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
+     * information is not available.
      */
-    public NetworkRegistrationState(int domain, int transportType, int regState,
-            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity) {
+    public NetworkRegistrationState(@Domain int domain, int transportType, @RegState int regState,
+                                    int accessNetworkTechnology, int rejectCause,
+                                    boolean emergencyOnly, int[] availableServices,
+                                    @Nullable CellIdentity cellIdentity) {
         mDomain = domain;
         mTransportType = transportType;
         mRegState = regState;
         mAccessNetworkTechnology = accessNetworkTechnology;
-        mReasonForDenial = reasonForDenial;
+        mRejectCause = rejectCause;
         mAvailableServices = availableServices;
         mCellIdentity = cellIdentity;
         mEmergencyOnly = emergencyOnly;
@@ -138,11 +152,13 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
-            int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
-        this(domain, transportType, regState, accessNetworkTechnology,
-                reasonForDenial, emergencyOnly, availableServices, cellIdentity);
+                                    int accessNetworkTechnology, int rejectCause,
+                                    boolean emergencyOnly, int[] availableServices,
+                                    @Nullable CellIdentity cellIdentity, boolean cssSupported,
+                                    int roamingIndicator, int systemIsInPrl,
+                                    int defaultRoamingIndicator) {
+        this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
+                availableServices, cellIdentity);
 
         mVoiceSpecificStates = new VoiceSpecificRegistrationStates(cssSupported, roamingIndicator,
                 systemIsInPrl, defaultRoamingIndicator);
@@ -153,10 +169,11 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls) {
-        this(domain, transportType, regState, accessNetworkTechnology,
-                reasonForDenial, emergencyOnly, availableServices, cellIdentity);
+                                    int accessNetworkTechnology, int rejectCause,
+                                    boolean emergencyOnly, int[] availableServices,
+                                    @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+        this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
+                availableServices, cellIdentity);
 
         mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
     }
@@ -166,7 +183,7 @@
         mTransportType = source.readInt();
         mRegState = source.readInt();
         mAccessNetworkTechnology = source.readInt();
-        mReasonForDenial = source.readInt();
+        mRejectCause = source.readInt();
         mEmergencyOnly = source.readBoolean();
         mAvailableServices = source.createIntArray();
         mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader());
@@ -211,10 +228,10 @@
     }
 
     /**
-     * @return Reason for denial from network.
+     * @return Network reject cause
      */
-    public int getReasonForDenial() {
-        return mReasonForDenial;
+    public int getRejectCause() {
+        return mRejectCause;
     }
 
     /**
@@ -265,7 +282,7 @@
                 .append(" regState=").append(regStateToString(mRegState))
                 .append(" accessNetworkTechnology=")
                 .append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
-                .append(" reasonForDenial=").append(mReasonForDenial)
+                .append(" rejectCause=").append(mRejectCause)
                 .append(" emergencyEnabled=").append(mEmergencyOnly)
                 .append(" supportedServices=").append(mAvailableServices)
                 .append(" cellIdentity=").append(mCellIdentity)
@@ -276,8 +293,8 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mTransportType, mDomain, mRegState, mAccessNetworkTechnology,
-                mReasonForDenial, mEmergencyOnly, mAvailableServices, mCellIdentity,
+        return Objects.hash(mDomain, mTransportType, mRegState, mAccessNetworkTechnology,
+                mRejectCause, mEmergencyOnly, mAvailableServices, mCellIdentity,
                 mVoiceSpecificStates, mDataSpecificStates);
     }
 
@@ -294,7 +311,7 @@
                 && mTransportType == other.mTransportType
                 && mRegState == other.mRegState
                 && mAccessNetworkTechnology == other.mAccessNetworkTechnology
-                && mReasonForDenial == other.mReasonForDenial
+                && mRejectCause == other.mRejectCause
                 && mEmergencyOnly == other.mEmergencyOnly
                 && (mAvailableServices == other.mAvailableServices
                     || Arrays.equals(mAvailableServices, other.mAvailableServices))
@@ -309,7 +326,7 @@
         dest.writeInt(mTransportType);
         dest.writeInt(mRegState);
         dest.writeInt(mAccessNetworkTechnology);
-        dest.writeInt(mReasonForDenial);
+        dest.writeInt(mRejectCause);
         dest.writeBoolean(mEmergencyOnly);
         dest.writeIntArray(mAvailableServices);
         dest.writeParcelable(mCellIdentity, 0);
diff --git a/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java b/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java
deleted file mode 100644
index f58ea7e..0000000
--- a/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.connectivity.tethering;
-
-import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_ABSENT;
-import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_LOADED;
-import static com.android.internal.telephony.IccCardConstants.INTENT_KEY_ICC_STATE;
-import static com.android.internal.telephony.TelephonyIntents.ACTION_SIM_STATE_CHANGED;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.reset;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.test.BroadcastInterceptingContext;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SimChangeListenerTest {
-    @Mock private Context mContext;
-    private BroadcastInterceptingContext mServiceContext;
-    private Handler mHandler;
-    private SimChangeListener mSCL;
-    private int mCallbackCount;
-
-    private void doCallback() { mCallbackCount++; }
-
-    private class MockContext extends BroadcastInterceptingContext {
-        MockContext(Context base) {
-            super(base);
-        }
-    }
-
-    @BeforeClass
-    public static void setUpBeforeClass() throws Exception {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
-    @Before public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        reset(mContext);
-        mServiceContext = new MockContext(mContext);
-        mHandler = new Handler(Looper.myLooper());
-        mCallbackCount = 0;
-        mSCL = new SimChangeListener(mServiceContext, mHandler, () -> doCallback());
-    }
-
-    @After public void tearDown() throws Exception {
-        if (mSCL != null) {
-            mSCL.stopListening();
-            mSCL = null;
-        }
-    }
-
-    private void sendSimStateChangeIntent(String state) {
-        final Intent intent = new Intent(ACTION_SIM_STATE_CHANGED);
-        intent.putExtra(INTENT_KEY_ICC_STATE, state);
-        mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-    }
-
-    @Test
-    public void testNotSeenFollowedBySeenCallsCallback() {
-        mSCL.startListening();
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(1, mCallbackCount);
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(2, mCallbackCount);
-
-        mSCL.stopListening();
-    }
-
-    @Test
-    public void testNotListeningDoesNotCallback() {
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-    }
-
-    @Test
-    public void testSeenOnlyDoesNotCallback() {
-        mSCL.startListening();
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-
-        mSCL.stopListening();
-    }
-}