Merge "Fix docs build" into lmp-mr1-dev
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4753099..ead89b3 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -504,6 +504,22 @@
         }
         return false;
     }
+    /**
+     * Return true if the given administrator component is currently being removed
+     * for the user.
+     * @hide
+     */
+    public boolean isRemovingAdmin(ComponentName who, int userId) {
+        if (mService != null) {
+            try {
+                return mService.isRemovingAdmin(who, userId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
+
 
     /**
      * Return a list of all currently active device administrator's component
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d144ae8..0ca60c0 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -196,4 +196,6 @@
 
     void setAutoTimeRequired(in ComponentName who, int userHandle, boolean required);
     boolean getAutoTimeRequired();
+
+    boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle);
 }
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 1e22eb3..194a53e 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -66,6 +66,8 @@
             ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid BNEP =
             ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid PBAP_PCE =
+            ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid PBAP_PSE =
             ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid MAP =
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4fe418a..4215f20 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -100,7 +100,7 @@
 
     /**
      * Identical to {@link #CONNECTIVITY_ACTION} broadcast, but sent without any
-     * historic {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}.
+     * applicable {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}.
      *
      * @hide
      */
@@ -428,6 +428,18 @@
     public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
 
     /**
+     * Default value for {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY} in
+     * milliseconds.  This was introduced because IPv6 routes seem to take a
+     * moment to settle - trying network activity before the routes are adjusted
+     * can lead to packets using the wrong interface or having the wrong IP address.
+     * This delay is a bit crude, but in the future hopefully we will have kernel
+     * notifications letting us know when it's safe to use the new network.
+     *
+     * @hide
+     */
+    public static final int CONNECTIVITY_CHANGE_DELAY_DEFAULT = 3000;
+
+    /**
      * @hide
      */
     public final static int REQUEST_ID_UNSET = 0;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3bc74ae..0c036d51 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6118,7 +6118,7 @@
 
         /**
          * The number of milliseconds to delay before sending out
-         * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcasts. Ignored.
+         * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcasts.
          *
          * @hide
          */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3dd9770..87b9971 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -363,6 +363,12 @@
         android:label="@string/permlab_receiveMms"
         android:description="@string/permdesc_receiveMms" />
 
+    <!-- Allows an application to filter carrier specific sms.
+         @hide -->
+    <permission android:name="android.permission.CARRIER_FILTER_SMS"
+        android:permissionGroup="android.permission-group.MESSAGES"
+        android:protectionLevel="signature|system" />
+
     <!-- @SystemApi Allows an application to receive emergency cell broadcast messages,
          to record or display them to the user.
          <p>Not for use by third-party applications.
@@ -2914,7 +2920,8 @@
          Any service that filters for this intent must be a carrier privileged app. -->
     <permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"
         android:label="@string/permlab_bindCarrierMessagingService"
-        android:description="@string/permdesc_bindCarrierMessagingService" />
+        android:description="@string/permdesc_bindCarrierMessagingService"
+        android:protectionLevel="signature|system" />
 
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
diff --git a/packages/SystemUI/res/layout/lland.xml b/packages/SystemUI/res/layout/lland.xml
index 053225d..71a16c9 100644
--- a/packages/SystemUI/res/layout/lland.xml
+++ b/packages/SystemUI/res/layout/lland.xml
@@ -31,10 +31,10 @@
             android:textSize="32sp"
             android:textColor="#FFAAAAAA"
             android:layout_marginTop="32dp"
-            android:layout_marginLeft="16dp"
-            android:layout_gravity="top|left"
-            android:paddingLeft="16dp"
-            android:paddingRight="16dp"
+            android:layout_marginStart="16dp"
+            android:layout_gravity="top|start"
+            android:paddingStart="16dp"
+            android:paddingEnd="16dp"
             android:paddingTop="8dp"
             android:paddingBottom="8dp"
             android:background="@drawable/scorecard"
diff --git a/packages/SystemUI/src/com/android/systemui/egg/LLand.java b/packages/SystemUI/src/com/android/systemui/egg/LLand.java
index 5de09a3..fa257b1 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/LLand.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/LLand.java
@@ -178,6 +178,9 @@
         setFocusable(true);
         PARAMS = new Params(getResources());
         mTimeOfDay = irand(0, SKIES.length);
+
+        // we assume everything will be laid out left|top
+        setLayoutDirection(LAYOUT_DIRECTION_LTR);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 8933d00..2e3e67a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -73,6 +73,7 @@
 
     private NotificationData.Entry mHeadsUp;
     private int mUser;
+    private String mMostRecentPackageName;
 
     public HeadsUpNotificationView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -117,6 +118,7 @@
         }
 
         if (mHeadsUp != null) {
+            mMostRecentPackageName = mHeadsUp.notification.getPackageName();
             mHeadsUp.row.setSystemExpanded(true);
             mHeadsUp.row.setSensitive(false);
             mHeadsUp.row.setHeadsUp(true);
@@ -198,8 +200,10 @@
     }
 
     private void snooze() {
-        mSnoozedPackages.put(snoozeKey(mHeadsUp.notification.getPackageName(), mUser),
-                SystemClock.elapsedRealtime() + mSnoozeLengthMs);
+        if (mMostRecentPackageName != null) {
+            mSnoozedPackages.put(snoozeKey(mMostRecentPackageName, mUser),
+                    SystemClock.elapsedRealtime() + mSnoozeLengthMs);
+        }
         releaseAndClose();
     }
 
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index fcca788..4f7e57f 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -220,7 +220,7 @@
             // OR 3. it looks like we use the same home app + version as before, but
             //       the signatures don't match so we treat them as different apps.
             final boolean needHomeBackup = (homeVersion != mStoredHomeVersion)
-                    || Objects.equals(home, mStoredHomeComponent)
+                    || !Objects.equals(home, mStoredHomeComponent)
                     || (home != null
                         && !BackupManagerService.signaturesMatch(mStoredHomeSigHashes, homeInfo));
             if (needHomeBackup) {
@@ -534,6 +534,7 @@
                             + ", redoing from start");
                     return;
                 }
+                pkg = in.readUTF();
             } else {
                 // This is an older version of the state file in which the lead element
                 // is not a STATE_FILE_VERSION string.  If that's the case, we want to
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 7b3e137..47bf188 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -61,6 +61,7 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Locale;
+import java.util.Random;
 import java.util.TimeZone;
 
 import static android.app.AlarmManager.RTC_WAKEUP;
@@ -114,8 +115,12 @@
     final Object mLock = new Object();
 
     long mNativeData;
-    private long mNextWakeup;
+
+    private final Random mFuzzer = new Random();
+    private long mNextWakeupBatchStart;     // nominal start of next wakeup's delivery window
+    private long mNextWakeup;               // actual scheduled next wakeup within that window
     private long mNextNonWakeup;
+
     int mBroadcastRefCount = 0;
     PowerManager.WakeLock mWakeLock;
     boolean mLastWakeLockUnimportantForLogging;
@@ -367,14 +372,27 @@
 
     static class BatchTimeOrder implements Comparator<Batch> {
         public int compare(Batch b1, Batch b2) {
-            long when1 = b1.start;
-            long when2 = b2.start;
-            if (when1 - when2 > 0) {
+            final long start1 = b1.start;
+            final long start2 = b2.start;
+            if (start1 > start2) {
                 return 1;
             }
-            if (when1 - when2 < 0) {
+            if (start1 < start2) {
                 return -1;
             }
+
+            // Identical trigger times.  As a secondary ordering, require that
+            // the batch with the shorter allowable delivery window sorts first.
+            final long interval1 = b1.end - b1.start;
+            final long interval2 = b2.end - b2.start;
+            if (interval1 > interval2) {
+                return 1;
+            }
+            if (interval2 < interval1) {
+                return -1;
+            }
+
+            // equal start + delivery window => they're identical
             return 0;
         }
     }
@@ -597,7 +615,7 @@
     @Override
     public void onStart() {
         mNativeData = init();
-        mNextWakeup = mNextNonWakeup = 0;
+        mNextWakeup = mNextWakeupBatchStart = mNextNonWakeup = 0;
 
         // We have to set current TimeZone info to kernel
         // because kernel doesn't keep this after reboot
@@ -805,8 +823,9 @@
                         "AlarmManager.set");
             }
 
+            // Exact alarms are standalone; inexact get batched together
             setImpl(type, triggerAtTime, windowLength, interval, operation,
-                    false, workSource, alarmClock);
+                    windowLength == AlarmManager.WINDOW_EXACT, workSource, alarmClock);
         }
 
         @Override
@@ -877,7 +896,7 @@
 
             pw.print("nowRTC="); pw.print(nowRTC);
             pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
-            pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
+            pw.print(" nowELAPSED="); pw.print(nowELAPSED);
             pw.println();
             if (!mInteractive) {
                 pw.print("Time since non-interactive: ");
@@ -1083,17 +1102,6 @@
         return true;
     }
 
-    private Batch findFirstWakeupBatchLocked() {
-        final int N = mAlarmBatches.size();
-        for (int i = 0; i < N; i++) {
-            Batch b = mAlarmBatches.get(i);
-            if (b.hasWakeups()) {
-                return b;
-            }
-        }
-        return null;
-    }
-
     private AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
         synchronized (mLock) {
             return mNextAlarmClockForUser.get(userId);
@@ -1228,16 +1236,48 @@
         // prior to that which contains no wakeups, we schedule that as well.
         long nextNonWakeup = 0;
         if (mAlarmBatches.size() > 0) {
-            final Batch firstWakeup = findFirstWakeupBatchLocked();
+            // Find the first wakeup alarm and note the following batch as well.  We'll be
+            // choosing a fuzzed delivery time within the first's allowable interval but
+            // ensuring that it does not encroach on the second's start time, to minimize
+            // alarm reordering.
+            Batch firstWakeup = null, nextAfterWakeup = null;
+            final int N = mAlarmBatches.size();
+            for (int i = 0; i < N; i++) {
+                Batch b = mAlarmBatches.get(i);
+                if (b.hasWakeups()) {
+                    firstWakeup = b;
+                    if (i < N-1) {
+                        nextAfterWakeup = mAlarmBatches.get(i+1);
+                    }
+                    break;
+                }
+            }
+
+            // There's a subtlety here: we depend on the invariant that if two batches
+            // exist with the same start time, the one with the shorter delivery window
+            // is sorted before the other.  This guarantees us that we need only look
+            // at the first [relevant] batch in the queue in order to schedule an alarm
+            // appropriately.
             final Batch firstBatch = mAlarmBatches.get(0);
-            if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
-                mNextWakeup = firstWakeup.start;
-                setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
+            if (firstWakeup != null && mNextWakeupBatchStart != firstWakeup.start) {
+                mNextWakeupBatchStart = mNextWakeup = firstWakeup.start;
+                final long windowEnd = (nextAfterWakeup == null)
+                        ? firstWakeup.end
+                        : Math.min(firstWakeup.end, nextAfterWakeup.start);
+                final long interval = windowEnd - firstWakeup.start;
+                // if the interval is over maxint we're into crazy land anyway, but
+                // just in case we check and don't fuzz if the conversion to int for
+                // random-number purposes would blow up
+                if (interval > 0 && interval < Integer.MAX_VALUE) {
+                    mNextWakeup += mFuzzer.nextInt((int) interval);
+                }
+                setLocked(ELAPSED_REALTIME_WAKEUP, mNextWakeup);
             }
             if (firstBatch != firstWakeup) {
                 nextNonWakeup = firstBatch.start;
             }
         }
+
         if (mPendingNonWakeupAlarms.size() > 0) {
             if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
                 nextNonWakeup = mNextNonWakeupDeliveryTime;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0f1ed0a..348aa1b 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -797,6 +797,17 @@
         throw new IllegalStateException("No free netIds");
     }
 
+    private int getConnectivityChangeDelay() {
+        final ContentResolver cr = mContext.getContentResolver();
+
+        /** Check system properties for the default value then use secure settings value, if any. */
+        int defaultDelay = SystemProperties.getInt(
+                "conn." + Settings.Global.CONNECTIVITY_CHANGE_DELAY,
+                ConnectivityManager.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
+        return Settings.Global.getInt(cr, Settings.Global.CONNECTIVITY_CHANGE_DELAY,
+                defaultDelay);
+    }
+
     private boolean teardown(NetworkStateTracker netTracker) {
         if (netTracker.teardown()) {
             netTracker.setTeardownRequested(true);
@@ -1468,6 +1479,11 @@
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
     }
 
+    private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
+        sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
+        sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs);
+    }
+
     private void sendInetConditionBroadcast(NetworkInfo info) {
         sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
     }
@@ -1499,6 +1515,10 @@
         sendStickyBroadcast(makeGeneralIntent(info, bcastType));
     }
 
+    private void sendGeneralBroadcastDelayed(NetworkInfo info, String bcastType, int delayMs) {
+        sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
+    }
+
     private void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) {
         Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
         intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
@@ -1532,6 +1552,19 @@
         }
     }
 
+    private void sendStickyBroadcastDelayed(Intent intent, int delayMs) {
+        if (delayMs <= 0) {
+            sendStickyBroadcast(intent);
+        } else {
+            if (VDBG) {
+                log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action="
+                        + intent.getAction());
+            }
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(
+                    EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
+        }
+    }
+
     void systemReady() {
         // start network sampling ..
         Intent intent = new Intent(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED);
@@ -4268,7 +4301,7 @@
         info.setType(type);
         if (connected) {
             info.setDetailedState(DetailedState.CONNECTED, null, info.getExtraInfo());
-            sendConnectedBroadcast(info);
+            sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
         } else {
             info.setDetailedState(DetailedState.DISCONNECTED, null, info.getExtraInfo());
             Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
@@ -4299,9 +4332,10 @@
             final Intent immediateIntent = new Intent(intent);
             immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
             sendStickyBroadcast(immediateIntent);
-            sendStickyBroadcast(intent);
+            sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
             if (newDefaultAgent != null) {
-                sendConnectedBroadcast(newDefaultAgent.networkInfo);
+                sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo,
+                getConnectivityChangeDelay());
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5b1d212..221a0a6 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9293,9 +9293,9 @@
                             "Attempt to launch content provider before system ready");
                 }
 
-                // Make sure that the user who owns this provider is started.  If not,
+                // Make sure that the user who owns this provider is running.  If not,
                 // we don't want to allow it to run.
-                if (mStartedUsers.get(userId) == null) {
+                if (!isUserRunningLocked(userId, false)) {
                     Slog.w(TAG, "Unable to launch app "
                             + cpi.applicationInfo.packageName + "/"
                             + cpi.applicationInfo.uid + " for provider "
@@ -15660,10 +15660,10 @@
         userId = handleIncomingUser(callingPid, callingUid, userId,
                 true, ALLOW_NON_FULL, "broadcast", callerPackage);
 
-        // Make sure that the user who is receiving this broadcast is started.
+        // Make sure that the user who is receiving this broadcast is running.
         // If not, we will just skip it.
 
-        if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
+        if (userId != UserHandle.USER_ALL && !isUserRunningLocked(userId, false)) {
             if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
                     & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
                 Slog.w(TAG, "Skipping broadcast of " + intent
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2201d2b..72a3337 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -120,7 +120,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
@@ -265,6 +264,8 @@
                 = new HashMap<ComponentName, ActiveAdmin>();
         final ArrayList<ActiveAdmin> mAdminList
                 = new ArrayList<ActiveAdmin>();
+        final ArrayList<ComponentName> mRemovingAdmins
+                = new ArrayList<ComponentName>();
 
         // This is the list of component allowed to start lock task mode.
         final List<String> mLockTaskPackages = new ArrayList<String>();
@@ -303,8 +304,6 @@
             if (Intent.ACTION_USER_REMOVED.equals(action)) {
                 removeUserData(userHandle);
             } else if (Intent.ACTION_USER_STARTED.equals(action)
-                    || Intent.ACTION_PACKAGE_CHANGED.equals(action)
-                    || Intent.ACTION_PACKAGE_REMOVED.equals(action)
                     || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
 
                 if (Intent.ACTION_USER_STARTED.equals(action)) {
@@ -313,8 +312,14 @@
                         mUserData.remove(userHandle);
                     }
                 }
-
-                handlePackagesChanged(userHandle);
+                handlePackagesChanged(null /* check all admins */, userHandle);
+            } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+                    || (Intent.ACTION_PACKAGE_ADDED.equals(action)
+                            && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false))) {
+                handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
+            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
+                    && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
             }
         }
     };
@@ -899,7 +904,7 @@
         }
     }
 
-    private void handlePackagesChanged(int userHandle) {
+    private void handlePackagesChanged(String packageName, int userHandle) {
         boolean removed = false;
         if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
         DevicePolicyData policy = getUserData(userHandle);
@@ -908,11 +913,17 @@
             for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
                 ActiveAdmin aa = policy.mAdminList.get(i);
                 try {
-                    if (pm.getPackageInfo(aa.info.getPackageName(), 0, userHandle) == null
-                            || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) {
-                        removed = true;
-                        policy.mAdminList.remove(i);
-                        policy.mAdminMap.remove(aa.info.getComponent());
+                    // If we're checking all packages or if the specific one we're checking matches,
+                    // then check if the package and receiver still exist.
+                    final String adminPackage = aa.info.getPackageName();
+                    if (packageName == null || packageName.equals(adminPackage)) {
+                        if (pm.getPackageInfo(adminPackage, 0, userHandle) == null
+                                || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle)
+                                    == null) {
+                            removed = true;
+                            policy.mAdminList.remove(i);
+                            policy.mAdminMap.remove(aa.info.getComponent());
+                        }
                     }
                 } catch (RemoteException re) {
                     // Shouldn't happen
@@ -1202,6 +1213,9 @@
     void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
         final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
         if (admin != null) {
+            synchronized (this) {
+                getUserData(userHandle).mRemovingAdmins.add(adminReceiver);
+            }
             sendAdminCommandLocked(admin,
                     DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
                     new BroadcastReceiver() {
@@ -1221,9 +1235,10 @@
                                 }
                                 saveSettingsLocked(userHandle);
                                 updateMaximumTimeToLockLocked(policy);
+                                policy.mRemovingAdmins.remove(adminReceiver);
                             }
                         }
-            });
+                    });
         }
     }
 
@@ -1788,6 +1803,18 @@
         }
     }
 
+    @Override
+    public boolean isRemovingAdmin(ComponentName adminReceiver, int userHandle) {
+        if (!mHasFeature) {
+            return false;
+        }
+        enforceCrossUserPermission(userHandle);
+        synchronized (this) {
+            DevicePolicyData policyData = getUserData(userHandle);
+            return policyData.mRemovingAdmins.contains(adminReceiver);
+        }
+    }
+
     public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId, int userHandle) {
         if (!mHasFeature) {
             return false;
@@ -4091,6 +4118,10 @@
                         ap.dump("    ", pw);
                     }
                 }
+                if (!policy.mRemovingAdmins.isEmpty()) {
+                    p.println("  Removing Device Admins (User " + policy.mUserHandle + "): "
+                            + policy.mRemovingAdmins);
+                }
 
                 pw.println(" ");
                 pw.print("  mPasswordOwner="); pw.println(policy.mPasswordOwner);
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index 3271ebf..9c03319 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -54,14 +54,14 @@
     public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
             ROUTE_SPEAKER;
 
-    /** @hide */
-    @Deprecated public final boolean isMuted;
+    /** Note: Deprecated, please do not use if possible. */
+    @SystemApi public final boolean isMuted;
 
-    /** @hide */
-    @Deprecated public final int route;
+    /** Note: Deprecated, please do not use if possible. */
+    @SystemApi public final int route;
 
-    /** @hide */
-    @Deprecated public final int supportedRouteMask;
+    /** Note: Deprecated, please do not use if possible. */
+    @SystemApi public final int supportedRouteMask;
 
     public AudioState(boolean muted, int route, int supportedRouteMask) {
         this.isMuted = muted;
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index dd4c45d..734fc68 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.telephony.RILConstants;
+
 /**
  * Object to indicate the phone radio type and access technology.
  *
@@ -107,6 +109,7 @@
      * @param outParcel The Parcel in which the object should be written.
      * @param flags Additional flags about how the object should be written.
      */
+    @Override
     public void writeToParcel(Parcel outParcel, int flags) {
         outParcel.writeInt(mPhoneId);
         outParcel.writeInt(mRadioAccessFamily);
@@ -131,5 +134,18 @@
             return new RadioAccessFamily[size];
         }
     };
+
+    public static int getRafFromNetworkType(int type) {
+        // TODO map from RILConstants.NETWORK_TYPE_* to RAF_*
+        switch (type) {
+            case RILConstants.NETWORK_MODE_WCDMA_PREF:
+            case RILConstants.NETWORK_MODE_GSM_UMTS:
+                return RAF_UMTS | RAF_GSM;
+            case RILConstants.NETWORK_MODE_GSM_ONLY:
+                return RAF_GSM;
+            default:
+                return RAF_UNKNOWN;
+        }
+    }
 }