Merge "Clean up connectivity tests." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index fc042d2..a0d47e4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5424,7 +5424,7 @@
     method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public java.util.List<byte[]> getInstalledCaCerts();
+    method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
@@ -5445,7 +5445,7 @@
     method public boolean getScreenCaptureDisabled(android.content.ComponentName);
     method public boolean getStorageEncryption(android.content.ComponentName);
     method public int getStorageEncryptionStatus();
-    method public boolean hasCaCertInstalled(byte[]);
+    method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
     method public boolean isActivePasswordSufficient();
@@ -28267,7 +28267,6 @@
     method public final void setRequestingRingback(boolean);
     method public final void setRinging();
     method public final void setStatusHints(android.telecomm.StatusHints);
-    method public final void startActivityFromInCall(android.app.PendingIntent);
     method public static java.lang.String stateToString(int);
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_DIALING = 3; // 0x3
@@ -28298,8 +28297,6 @@
     method public final java.util.Collection<android.telecomm.Connection> getAllConnections();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecomm.Connection, android.telecomm.Connection);
-    method public void onConnectionAdded(android.telecomm.Connection);
-    method public void onConnectionRemoved(android.telecomm.Connection);
     method public android.telecomm.Connection onCreateIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
     method public android.telecomm.Connection onCreateOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecomm.RemoteConference);
@@ -28327,10 +28324,15 @@
     method public java.lang.CharSequence getLabel();
     method public java.lang.CharSequence getShortDescription();
     method public java.lang.String getSubscriptionNumber();
+    method public java.util.List<java.lang.String> getSupportedUriSchemes();
+    method public boolean supportsUriScheme(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String SCHEME_SIP = "sip";
+    field public static final java.lang.String SCHEME_TEL = "tel";
+    field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail";
   }
 
   public static class PhoneAccount.Builder {
@@ -28343,6 +28345,8 @@
     method public android.telecomm.PhoneAccount.Builder withLabel(java.lang.CharSequence);
     method public android.telecomm.PhoneAccount.Builder withShortDescription(java.lang.CharSequence);
     method public android.telecomm.PhoneAccount.Builder withSubscriptionNumber(java.lang.String);
+    method public android.telecomm.PhoneAccount.Builder withSupportedUriScheme(java.lang.String);
+    method public android.telecomm.PhoneAccount.Builder withSupportedUriSchemes(java.util.List<java.lang.String>);
   }
 
   public class PhoneAccountHandle implements android.os.Parcelable {
@@ -28445,7 +28449,6 @@
     method public void onParentChanged(android.telecomm.RemoteConnection, android.telecomm.RemoteConnection);
     method public void onPostDialWait(android.telecomm.RemoteConnection, java.lang.String);
     method public void onRequestingRingback(android.telecomm.RemoteConnection, boolean);
-    method public void onStartActivityFromInCall(android.telecomm.RemoteConnection, android.app.PendingIntent);
     method public void onStateChanged(android.telecomm.RemoteConnection, int);
     method public void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints);
   }
@@ -28471,9 +28474,10 @@
     method public void addNewIncomingCall(android.telecomm.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
     method public void clearAccounts(java.lang.String);
-    method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount();
+    method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
     method public java.util.List<android.telecomm.PhoneAccountHandle> getEnabledPhoneAccounts();
     method public android.telecomm.PhoneAccount getPhoneAccount(android.telecomm.PhoneAccountHandle);
+    method public java.util.List<android.telecomm.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
     method public boolean handleMmi(java.lang.String);
     method public boolean hasMultipleEnabledAccounts();
     method public boolean isInCall();
@@ -28849,23 +28853,23 @@
   }
 
   public final class SmsManager {
-    method public android.net.Uri addMultimediaMessageDraft(byte[]);
+    method public android.net.Uri addMultimediaMessageDraft(android.net.Uri);
     method public android.net.Uri addTextMessageDraft(java.lang.String, java.lang.String);
     method public boolean archiveStoredConversation(long, boolean);
     method public boolean deleteStoredConversation(long);
     method public boolean deleteStoredMessage(android.net.Uri);
     method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
-    method public void downloadMultimediaMessage(java.lang.String, android.content.ContentValues, android.app.PendingIntent);
+    method public void downloadMultimediaMessage(java.lang.String, android.net.Uri, android.content.ContentValues, android.app.PendingIntent);
     method public boolean getAutoPersisting();
     method public android.os.Bundle getCarrierConfigValues();
     method public static android.telephony.SmsManager getDefault();
-    method public static android.telephony.SmsManager getSmsManagerForSubId(long);
+    method public static android.telephony.SmsManager getSmsManagerUsingSubId(long);
     method public long getSubId();
-    method public android.net.Uri importMultimediaMessage(byte[], java.lang.String, long, boolean, boolean);
+    method public android.net.Uri importMultimediaMessage(android.net.Uri, java.lang.String, long, boolean, boolean);
     method public android.net.Uri importTextMessage(java.lang.String, int, java.lang.String, long, boolean, boolean);
     method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent);
     method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
-    method public void sendMultimediaMessage(byte[], java.lang.String, android.content.ContentValues, android.app.PendingIntent);
+    method public void sendMultimediaMessage(android.net.Uri, java.lang.String, android.content.ContentValues, android.app.PendingIntent);
     method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
     method public void sendStoredMultimediaMessage(android.net.Uri, android.content.ContentValues, android.app.PendingIntent);
     method public void sendStoredMultipartTextMessage(android.net.Uri, java.lang.String, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
@@ -28876,6 +28880,8 @@
     method public void updateMmsSendStatus(int, boolean);
     method public void updateSmsSendStatus(int, boolean);
     method public boolean updateStoredMessageStatus(android.net.Uri, android.content.ContentValues);
+    field public static final java.lang.String MESSAGE_STATUS_READ = "read";
+    field public static final java.lang.String MESSAGE_STATUS_SEEN = "seen";
     field public static final java.lang.String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled";
     field public static final java.lang.String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars";
     field public static final java.lang.String MMS_CONFIG_ALIAS_MIN_CHARS = "aliasMinChars";
@@ -28904,10 +28910,9 @@
     field public static final java.lang.String MMS_CONFIG_UA_PROF_TAG_NAME = "uaProfTagName";
     field public static final java.lang.String MMS_CONFIG_UA_PROF_URL = "uaProfUrl";
     field public static final java.lang.String MMS_CONFIG_USER_AGENT = "userAgent";
-    field public static final java.lang.String MESSAGE_STATUS_READ = "read";
-    field public static final java.lang.String MESSAGE_STATUS_SEEN = "seen";
     field public static final int MMS_ERROR_HTTP_FAILURE = 4; // 0x4
     field public static final int MMS_ERROR_INVALID_APN = 2; // 0x2
+    field public static final int MMS_ERROR_IO_ERROR = 5; // 0x5
     field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3
     field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1
     field public static final java.lang.String MMS_EXTRA_DATA = "data";
@@ -32916,6 +32921,7 @@
     field public static final int KEYCODE_GUIDE = 172; // 0xac
     field public static final int KEYCODE_H = 36; // 0x24
     field public static final int KEYCODE_HEADSETHOOK = 79; // 0x4f
+    field public static final int KEYCODE_HELP = 259; // 0x103
     field public static final int KEYCODE_HENKAN = 214; // 0xd6
     field public static final int KEYCODE_HOME = 3; // 0x3
     field public static final int KEYCODE_I = 37; // 0x25
@@ -33016,9 +33022,36 @@
     field public static final int KEYCODE_T = 48; // 0x30
     field public static final int KEYCODE_TAB = 61; // 0x3d
     field public static final int KEYCODE_TV = 170; // 0xaa
+    field public static final int KEYCODE_TV_ANTENNA_CABLE = 242; // 0xf2
+    field public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252; // 0xfc
+    field public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254; // 0xfe
+    field public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253; // 0xfd
+    field public static final int KEYCODE_TV_CONTENTS_MENU = 256; // 0x100
     field public static final int KEYCODE_TV_DATA_SERVICE = 230; // 0xe6
     field public static final int KEYCODE_TV_INPUT = 178; // 0xb2
+    field public static final int KEYCODE_TV_INPUT_COMPONENT_1 = 249; // 0xf9
+    field public static final int KEYCODE_TV_INPUT_COMPONENT_2 = 250; // 0xfa
+    field public static final int KEYCODE_TV_INPUT_COMPOSITE_1 = 247; // 0xf7
+    field public static final int KEYCODE_TV_INPUT_COMPOSITE_2 = 248; // 0xf8
+    field public static final int KEYCODE_TV_INPUT_HDMI_1 = 243; // 0xf3
+    field public static final int KEYCODE_TV_INPUT_HDMI_2 = 244; // 0xf4
+    field public static final int KEYCODE_TV_INPUT_HDMI_3 = 245; // 0xf5
+    field public static final int KEYCODE_TV_INPUT_HDMI_4 = 246; // 0xf6
+    field public static final int KEYCODE_TV_INPUT_VGA_1 = 251; // 0xfb
+    field public static final int KEYCODE_TV_MEDIA_CONTEXT_MENU = 257; // 0x101
+    field public static final int KEYCODE_TV_NETWORK = 241; // 0xf1
+    field public static final int KEYCODE_TV_NUMBER_ENTRY = 234; // 0xea
     field public static final int KEYCODE_TV_POWER = 177; // 0xb1
+    field public static final int KEYCODE_TV_RADIO_SERVICE = 232; // 0xe8
+    field public static final int KEYCODE_TV_SATELLITE = 237; // 0xed
+    field public static final int KEYCODE_TV_SATELLITE_BS = 238; // 0xee
+    field public static final int KEYCODE_TV_SATELLITE_CS = 239; // 0xef
+    field public static final int KEYCODE_TV_SATELLITE_SERVICE = 240; // 0xf0
+    field public static final int KEYCODE_TV_TELETEXT = 233; // 0xe9
+    field public static final int KEYCODE_TV_TERRESTRIAL_ANALOG = 235; // 0xeb
+    field public static final int KEYCODE_TV_TERRESTRIAL_DIGITAL = 236; // 0xec
+    field public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258; // 0x102
+    field public static final int KEYCODE_TV_ZOOM_MODE = 255; // 0xff
     field public static final int KEYCODE_U = 49; // 0x31
     field public static final int KEYCODE_UNKNOWN = 0; // 0x0
     field public static final int KEYCODE_V = 50; // 0x32
@@ -36762,7 +36795,6 @@
     method public deprecated void onGlobalFocusChanged(android.view.View, android.view.View);
     method public void onPause();
     method public void onResume();
-    method public static void optOutDataReductionProxy();
     method public boolean overlayHorizontalScrollbar();
     method public boolean overlayVerticalScrollbar();
     method public boolean pageDown(boolean);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index bc54055..3e03893 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -18,12 +18,14 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.os.BatteryStats;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+
 import com.android.internal.app.ProcessStats;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.util.FastPrintWriter;
@@ -2464,7 +2466,11 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Gets the userId of the current foreground user. Requires system permissions.
+     * @hide
+     */
+    @SystemApi
     public static int getCurrentUser() {
         UserInfo ui;
         try {
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 613e248..ad4a22b 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -151,6 +151,7 @@
             mEnterActivityOptions = options;
             mIsEnterTriggered = false;
             if (mEnterActivityOptions.isReturning()) {
+                restoreExitedViews();
                 int result = mEnterActivityOptions.getResultCode();
                 if (result != 0) {
                     activity.onActivityReenter(result, mEnterActivityOptions.getResultData());
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 47d3fd6..4126647 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -170,7 +170,7 @@
 
     private void sendSharedElementDestination() {
         boolean allReady;
-        if (allowOverlappingTransitions()) {
+        if (allowOverlappingTransitions() && getEnterViewsTransition() != null) {
             allReady = false;
         } else {
             allReady = !getDecor().isLayoutRequested();
@@ -466,6 +466,7 @@
             Drawable background = getDecor().getBackground();
             if (background != null) {
                 background = background.mutate();
+                getWindow().setBackgroundDrawable(background);
                 mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 255);
                 mBackgroundAnimator.setDuration(getFadeDuration());
                 mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 3760b96..231c93f 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -140,7 +140,8 @@
         if (getDecor() != null) {
             getDecor().suppressLayout(true);
         }
-        if (!mSharedElements.isEmpty() && getSharedElementTransition() != null) {
+        if (mExitSharedElementBundle != null && !mExitSharedElementBundle.isEmpty() &&
+                !mSharedElements.isEmpty() && getSharedElementTransition() != null) {
             startTransition(new Runnable() {
                 public void run() {
                     startSharedElementExit();
@@ -259,6 +260,8 @@
             ViewGroup decor = getDecor();
             Drawable background;
             if (decor != null && (background = decor.getBackground()) != null) {
+                background = background.mutate();
+                getWindow().setBackgroundDrawable(background);
                 mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 0);
                 mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
                     @Override
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 6cc6fb2..ebeaf34 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1917,7 +1917,7 @@
             mPeople = new ArrayList<String>();
 
             mColorUtil = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.L ?
-                    NotificationColorUtil.getInstance() : null;
+                    NotificationColorUtil.getInstance(mContext) : null;
         }
 
         /**
@@ -2890,7 +2890,7 @@
         }
 
         private void processLegacyAction(Action action, RemoteViews button) {
-            if (!isLegacy() || mColorUtil.isGrayscale(mContext, action.icon)) {
+            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, action.icon)) {
                 button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0,
                         mContext.getResources().getColor(R.color.notification_action_color_filter),
                         PorterDuff.Mode.MULTIPLY);
@@ -2909,7 +2909,7 @@
          * Apply any necessary background to smallIcons being used in the largeIcon spot.
          */
         private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) {
-            if (!isLegacy() || mColorUtil.isGrayscale(mContext, largeIconId)) {
+            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) {
                 applyLargeIconBackground(contentView);
             }
         }
@@ -2920,7 +2920,7 @@
          */
         // TODO: also check bounds, transparency, that sort of thing.
         private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) {
-            if (isLegacy() && mColorUtil.isGrayscale(largeIcon)) {
+            if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) {
                 applyLargeIconBackground(contentView);
             } else {
                 removeLargeIconBackground(contentView);
@@ -2956,7 +2956,7 @@
          */
         private void processSmallRightIcon(int smallIconDrawableId,
                 RemoteViews contentView) {
-            if (!isLegacy() || mColorUtil.isGrayscale(mContext, smallIconDrawableId)) {
+            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) {
                 contentView.setDrawableParameters(R.id.right_icon, false, -1,
                         0xFFFFFFFF,
                         PorterDuff.Mode.SRC_ATOP, -1);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9ed8960..282444a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -115,13 +115,14 @@
         = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
 
     /**
-     * A {@link Parcelable} extra of type {@link PersistableBundle} that allows a mobile device
-     * management application that starts managed profile provisioning to pass data to itself on the
-     * managed profile when provisioning completes. The mobile device management application sends
-     * this extra in an intent with the action {@link #ACTION_PROVISION_MANAGED_PROFILE} and
-     * receives it in {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with
-     * the action {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is
-     * not changed during the managed profile provisioning.
+     * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
+     * a mobile device management application that starts managed profile provisioning to pass data
+     * to itself on the managed profile when provisioning completes. The mobile device management
+     * application sends this extra in an intent with the action
+     * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in
+     * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
+     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed
+     * during the managed profile provisioning.
      */
     public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
             "android.app.extra.ADMIN_EXTRA_BUNDLE";
@@ -1785,16 +1786,24 @@
      * If a user has installed any certificates by other means than device policy these will be
      * included too.
      *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return a List of byte[] arrays, each encoding one user CA certificate.
      */
-    public List<byte[]> getInstalledCaCerts() {
-        final TrustedCertificateStore certStore = new TrustedCertificateStore();
+    public List<byte[]> getInstalledCaCerts(ComponentName admin) {
         List<byte[]> certs = new ArrayList<byte[]>();
-        for (String alias : certStore.userAliases()) {
+        if (mService != null) {
             try {
-                certs.add(certStore.getCertificate(alias).getEncoded());
-            } catch (CertificateException ce) {
-                Log.w(TAG, "Could not encode certificate: " + alias, ce);
+                mService.enforceCanManageCaCerts(admin);
+                final TrustedCertificateStore certStore = new TrustedCertificateStore();
+                for (String alias : certStore.userAliases()) {
+                    try {
+                        certs.add(certStore.getCertificate(alias).getEncoded());
+                    } catch (CertificateException ce) {
+                        Log.w(TAG, "Could not encode certificate: " + alias, ce);
+                    }
+                }
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed talking with device policy service", re);
             }
         }
         return certs;
@@ -1821,13 +1830,19 @@
     /**
      * Returns whether this certificate is installed as a trusted CA.
      *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param certBuffer encoded form of the certificate to look up.
      */
-    public boolean hasCaCertInstalled(byte[] certBuffer) {
-        try {
-            return getCaCertAlias(certBuffer) != null;
-        } catch (CertificateException ce) {
-            Log.w(TAG, "Could not parse certificate", ce);
+    public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) {
+        if (mService != null) {
+            try {
+                mService.enforceCanManageCaCerts(admin);
+                return getCaCertAlias(certBuffer) != null;
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed talking with device policy service", re);
+            } catch (CertificateException ce) {
+                Log.w(TAG, "Could not parse certificate", ce);
+            }
         }
         return false;
     }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c984cf9..57d8b95 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -124,6 +124,7 @@
 
     boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
     void uninstallCaCert(in ComponentName admin, in String alias);
+    void enforceCanManageCaCerts(in ComponentName admin);
 
     void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
     void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index ca7022d..89efeb2 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -21,14 +21,24 @@
 import android.content.Context;
 
 /**
- * Class for scheduling various types of jobs with the scheduling framework on the device.
+ * This is an API for scheduling various types of jobs against the framework that will be executed
+ * in your application's own process.
+ * <p>
  * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
- * and how to construct them.
+ * and how to construct them. You will construct these JobInfo objects and pass them to the
+ * JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the
+ * system will execute this job on your application's {@link android.app.job.JobService}.
+ * You identify which JobService is meant to execute the logic for your job when you create the
+ * JobInfo with
+ * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}.
+ * </p>
+ * <p>
  * The framework will be intelligent about when you receive your callbacks, and attempt to batch
  * and defer them as much as possible. Typically if you don't specify a deadline on your job, it
  * can be run at any moment depending on the current state of the JobScheduler's internal queue,
  * however it might be deferred as long as until the next time the device is connected to a power
  * source.
+ * </p>
  * <p>You do not
  * instantiate this class directly; instead, retrieve it through
  * {@link android.content.Context#getSystemService
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index b98e5ae..36997e5 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -375,6 +375,14 @@
             } // else ASSERT(mPort == channel)
             ret = 0;
         } catch (IOException e) {
+            if (mPfd != null) {
+                try {
+                    mPfd.close();
+                } catch (IOException e1) {
+                    Log.e(TAG, "bindListen, close mPfd: " + e1);
+                }
+                mPfd = null;
+            }
             Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
             return -1;
         }
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 5ce9d5c..0ff5f6a 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -234,6 +234,7 @@
      * @return user id of the current process
      * @hide
      */
+    @SystemApi
     public static final int myUserId() {
         return getUserId(Process.myUid());
     }
@@ -253,7 +254,11 @@
         mHandle = h;
     }
 
-    /** @hide */
+    /**
+     * Returns the userId stored in this UserHandle.
+     * @hide
+     */
+    @SystemApi
     public int getIdentifier() {
         return mHandle;
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f793667..59220e1 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -15,6 +15,7 @@
  */
 package android.os;
 
+import android.annotation.SystemApi;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.content.Context;
@@ -424,6 +425,19 @@
     }
 
     /**
+     * Checks if the calling app is running in a managed profile.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
+     * @return whether the caller is in a managed profile.
+     * @hide
+     */
+    @SystemApi
+    public boolean isManagedProfile() {
+        UserInfo user = getUserInfo(UserHandle.myUserId());
+        return user != null ? user.isManagedProfile() : false;
+    }
+
+    /**
      * Return whether the given user is actively running.  This means that
      * the user is in the "started" state, not "stopped" -- it is currently
      * allowed to run code through scheduled alarms, receiving broadcasts,
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index d579f54..cb0a875 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -45,6 +45,10 @@
     private static final String PROPNAME_TRANSFORMS = "android:changeTransform:transforms";
     private static final String PROPNAME_PARENT = "android:changeTransform:parent";
     private static final String PROPNAME_PARENT_MATRIX = "android:changeTransform:parentMatrix";
+    private static final String PROPNAME_INTERMEDIATE_PARENT_MATRIX =
+            "android:changeTransform:intermediateParentMatrix";
+    private static final String PROPNAME_INTERMEDIATE_MATRIX =
+            "android:changeTransform:intermediateMatrix";
 
     private static final String[] sTransitionProperties = {
             PROPNAME_MATRIX,
@@ -172,6 +176,10 @@
             parent.transformMatrixToGlobal(parentMatrix);
             parentMatrix.preTranslate(-parent.getScrollX(), -parent.getScrollY());
             transitionValues.values.put(PROPNAME_PARENT_MATRIX, parentMatrix);
+            transitionValues.values.put(PROPNAME_INTERMEDIATE_MATRIX,
+                    view.getTag(R.id.transitionTransform));
+            transitionValues.values.put(PROPNAME_INTERMEDIATE_PARENT_MATRIX,
+                    view.getTag(R.id.parentMatrix));
         }
         return;
     }
@@ -199,12 +207,13 @@
         ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
         boolean handleParentChange = mReparent && !parentsMatch(startParent, endParent);
 
-        Matrix startMatrix = (Matrix) startValues.view.getTag(R.id.transitionTransform);
+        Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_INTERMEDIATE_MATRIX);
         if (startMatrix != null) {
             startValues.values.put(PROPNAME_MATRIX, startMatrix);
         }
 
-        Matrix startParentMatrix = (Matrix) startValues.view.getTag(R.id.parentMatrix);
+        Matrix startParentMatrix = (Matrix)
+                startValues.values.get(PROPNAME_INTERMEDIATE_PARENT_MATRIX);
         if (startParentMatrix != null) {
             startValues.values.put(PROPNAME_PARENT_MATRIX, startParentMatrix);
         }
@@ -250,9 +259,11 @@
         ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY,
                 new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
 
+        final Matrix finalEndMatrix = endMatrix;
+
         AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
             private boolean mIsCanceled;
-            private Matrix mTempMatrix;
+            private Matrix mTempMatrix = new Matrix();
 
             @Override
             public void onAnimationCancel(Animator animation) {
@@ -262,8 +273,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 if (!mIsCanceled) {
-                    view.setTagInternal(R.id.transitionTransform, null);
-                    view.setTagInternal(R.id.parentMatrix, null);
+                    setCurrentMatrix(finalEndMatrix);
                 }
                 ANIMATION_MATRIX_PROPERTY.set(view, null);
                 transforms.restore(view);
@@ -273,19 +283,19 @@
             public void onAnimationPause(Animator animation) {
                 ValueAnimator animator = (ValueAnimator) animation;
                 Matrix currentMatrix = (Matrix) animator.getAnimatedValue();
-                if (mTempMatrix == null) {
-                    mTempMatrix = new Matrix(currentMatrix);
-                } else {
-                    mTempMatrix.set(currentMatrix);
-                }
-                view.setTagInternal(R.id.transitionTransform, mTempMatrix);
-                transforms.restore(view);
+                setCurrentMatrix(currentMatrix);
             }
 
             @Override
             public void onAnimationResume(Animator animation) {
                 setIdentityTransforms(view);
             }
+
+            private void setCurrentMatrix(Matrix currentMatrix) {
+                mTempMatrix.set(currentMatrix);
+                view.setTagInternal(R.id.transitionTransform, mTempMatrix);
+                transforms.restore(view);
+            }
         };
 
         animator.addListener(listener);
@@ -423,6 +433,8 @@
         public void onTransitionEnd(Transition transition) {
             transition.removeListener(this);
             GhostView.removeGhost(mView);
+            mView.setTagInternal(R.id.transitionTransform, null);
+            mView.setTagInternal(R.id.parentMatrix, null);
         }
 
         @Override
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 964b054..0701b53 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -660,8 +660,96 @@
     /** Key code constant: Voice Assist key.
      * Launches the global voice assist activity. Not delivered to applications. */
     public static final int KEYCODE_VOICE_ASSIST = 231;
+    /** Key code constant: Radio key.
+     * Toggles TV service / Radio service. */
+    public static final int KEYCODE_TV_RADIO_SERVICE = 232;
+    /** Key code constant: Teletext key.
+     * Displays Teletext service. */
+    public static final int KEYCODE_TV_TELETEXT = 233;
+    /** Key code constant: Number entry key.
+     * Initiates to enter multi-digit channel nubmber when each digit key is assigned
+     * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC
+     * User Control Code. */
+    public static final int KEYCODE_TV_NUMBER_ENTRY = 234;
+    /** Key code constant: Analog Terrestrial key.
+     * Switches to analog terrestrial broadcast service. */
+    public static final int KEYCODE_TV_TERRESTRIAL_ANALOG = 235;
+    /** Key code constant: Digital Terrestrial key.
+     * Switches to digital terrestrial broadcast service. */
+    public static final int KEYCODE_TV_TERRESTRIAL_DIGITAL = 236;
+    /** Key code constant: Satellite key.
+     * Switches to digital satellite broadcast service. */
+    public static final int KEYCODE_TV_SATELLITE = 237;
+    /** Key code constant: BS key.
+     * Switches to BS digital satellite broadcasting service available in Japan. */
+    public static final int KEYCODE_TV_SATELLITE_BS = 238;
+    /** Key code constant: CS key.
+     * Switches to CS digital satellite broadcasting service available in Japan. */
+    public static final int KEYCODE_TV_SATELLITE_CS = 239;
+    /** Key code constant: BS/CS key.
+     * Toggles between BS and CS digital satellite services. */
+    public static final int KEYCODE_TV_SATELLITE_SERVICE = 240;
+    /** Key code constant: Toggle Network key.
+     * Toggles selecting broacast services. */
+    public static final int KEYCODE_TV_NETWORK = 241;
+    /** Key code constant: Antenna/Cable key.
+     * Toggles broadcast input source between antenna and cable. */
+    public static final int KEYCODE_TV_ANTENNA_CABLE = 242;
+    /** Key code constant: HDMI #1 key.
+     * Switches to HDMI input #1. */
+    public static final int KEYCODE_TV_INPUT_HDMI_1 = 243;
+    /** Key code constant: HDMI #2 key.
+     * Switches to HDMI input #2. */
+    public static final int KEYCODE_TV_INPUT_HDMI_2 = 244;
+    /** Key code constant: HDMI #3 key.
+     * Switches to HDMI input #3. */
+    public static final int KEYCODE_TV_INPUT_HDMI_3 = 245;
+    /** Key code constant: HDMI #4 key.
+     * Switches to HDMI input #4. */
+    public static final int KEYCODE_TV_INPUT_HDMI_4 = 246;
+    /** Key code constant: Composite #1 key.
+     * Switches to composite video input #1. */
+    public static final int KEYCODE_TV_INPUT_COMPOSITE_1 = 247;
+    /** Key code constant: Composite #2 key.
+     * Switches to composite video input #2. */
+    public static final int KEYCODE_TV_INPUT_COMPOSITE_2 = 248;
+    /** Key code constant: Component #1 key.
+     * Switches to component video input #1. */
+    public static final int KEYCODE_TV_INPUT_COMPONENT_1 = 249;
+    /** Key code constant: Component #2 key.
+     * Switches to component video input #2. */
+    public static final int KEYCODE_TV_INPUT_COMPONENT_2 = 250;
+    /** Key code constant: VGA #1 key.
+     * Switches to VGA (analog RGB) input #1. */
+    public static final int KEYCODE_TV_INPUT_VGA_1 = 251;
+    /** Key code constant: Audio description key.
+     * Toggles audio description off / on. */
+    public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252;
+    /** Key code constant: Audio description mixing volume up key.
+     * Louden audio description volume as compared with normal audio volume. */
+    public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253;
+    /** Key code constant: Audio description mixing volume down key.
+     * Lessen audio description volume as compared with normal audio volume. */
+    public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254;
+    /** Key code constant: Zoom mode key.
+     * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */
+    public static final int KEYCODE_TV_ZOOM_MODE = 255;
+    /** Key code constant: Contents menu key.
+     * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control
+     * Code */
+    public static final int KEYCODE_TV_CONTENTS_MENU = 256;
+    /** Key code constant: Media context menu key.
+     * Goes to the context menu of media contents. Corresponds to Media Context-sensitive
+     * Menu (0x11) of CEC User Control Code. */
+    public static final int KEYCODE_TV_MEDIA_CONTEXT_MENU = 257;
+    /** Key code constant: Timer programming key.
+     * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of
+     * CEC User Control Code. */
+    public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258;
+    /** Key code constant: Help key. */
+    public static final int KEYCODE_HELP = 259;
 
-    private static final int LAST_KEYCODE = KEYCODE_VOICE_ASSIST;
+    private static final int LAST_KEYCODE = KEYCODE_HELP;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index ca08ecc..5d2822d 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -126,7 +126,7 @@
     void destroy() {
         mInitialized = false;
         updateEnabledState(null);
-        nDestroyCanvasAndSurface(mNativeProxy);
+        nDestroy(mNativeProxy);
     }
 
     private void updateEnabledState(Surface surface) {
@@ -488,7 +488,7 @@
     private static native void nSetOpaque(long nativeProxy, boolean opaque);
     private static native int nSyncAndDrawFrame(long nativeProxy,
             long frameTimeNanos, long recordDuration, float density);
-    private static native void nDestroyCanvasAndSurface(long nativeProxy);
+    private static native void nDestroy(long nativeProxy);
     private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
 
     private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fce6f0b..21e7c6b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4908,36 +4908,11 @@
             }
 
             onFocusChanged(true, direction, previouslyFocusedRect);
-            manageFocusHotspot(true, oldFocus);
             refreshDrawableState();
         }
     }
 
     /**
-     * Forwards focus information to the background drawable, if necessary. When
-     * the view is gaining focus, <code>v</code> is the previous focus holder.
-     * When the view is losing focus, <code>v</code> is the next focus holder.
-     *
-     * @param focused whether this view is focused
-     * @param v previous or the next focus holder, or null if none
-     */
-    private void manageFocusHotspot(boolean focused, View v) {
-        final Rect r = new Rect();
-        if (v != null && mAttachInfo != null) {
-            v.getHotspotBounds(r);
-            final int[] location = mAttachInfo.mTmpLocation;
-            getLocationOnScreen(location);
-            r.offset(-location[0], -location[1]);
-        } else {
-            r.set(0, 0, mRight - mLeft, mBottom - mTop);
-        }
-
-        final float x = r.exactCenterX();
-        final float y = r.exactCenterY();
-        drawableHotspotChanged(x, y);
-    }
-
-    /**
      * Populates <code>outRect</code> with the hotspot bounds. By default,
      * the hotspot bounds are identical to the screen bounds.
      *
@@ -5060,8 +5035,6 @@
             }
 
             onFocusChanged(false, 0, null);
-
-            manageFocusHotspot(false, focused);
             refreshDrawableState();
 
             if (propagate && (!refocus || !rootViewRequestFocus())) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e1f19ee..edfa7af 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1810,21 +1810,6 @@
     }
 
     /**
-     * Sets whether the application wants to opt out from using the Data Reduction Proxy
-     * service.
-     * Data reduction proxy can only be enabled by the user and will almost always be
-     * transparent to the application. In rare cases where using the proxy interferes
-     * with the app, the application developer can use this API to opt out from using the
-     * proxy. Note that this may increase network bandwidth usage.
-     *
-     * See <a href=http://developer.chrome.com/multidevice/data-compression>
-     * Data Compression Proxy</a>
-     */
-    public static void optOutDataReductionProxy() {
-        getFactory().getStatics().optOutDataReductionProxy();
-    }
-
-    /**
      * Gets the list of currently loaded plugins.
      *
      * @return the list of currently loaded plugins
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 48f3ca3..20bb932 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -61,12 +61,6 @@
 
         /**
          * Implements the API method:
-         * {@link android.webkit.WebView#optOutDataReductionProxy() }
-         */
-        void optOutDataReductionProxy();
-
-        /**
-         * Implements the API method:
          * {@link android.webkit.WebView#setSlowWholeDocumentDrawEnabled(boolean) }
          */
         void enableSlowWholeDocumentDraw();
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index ee17b78..345eafb 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1878,6 +1878,9 @@
         if (mOnValueChangeListener != null) {
             mOnValueChangeListener.onValueChange(this, previous, mValue);
         }
+
+        mAccessibilityNodeProvider.sendAccessibilityEventForVirtualText(
+                AccessibilityEvent.TYPE_VIEW_FOCUSED);
     }
 
     /**
@@ -2556,6 +2559,7 @@
             getLocationOnScreen(locationOnScreen);
             boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
             info.setBoundsInScreen(boundsInScreen);
+            info.setLiveRegion(View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE);
             return info;
         }
 
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index a5ce6e0..c153904 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -17,6 +17,10 @@
 package com.android.internal.util;
 
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
 
 /**
  * Utility class for image analysis and processing.
@@ -31,17 +35,49 @@
     // Alpha amount for which values below are considered transparent.
     private static final int ALPHA_TOLERANCE = 50;
 
+    // Size of the smaller bitmap we're actually going to scan.
+    private static final int COMPACT_BITMAP_SIZE = 64; // pixels
+
     private int[] mTempBuffer;
+    private Bitmap mTempCompactBitmap;
+    private Canvas mTempCompactBitmapCanvas;
+    private Paint mTempCompactBitmapPaint;
+    private final Matrix mTempMatrix = new Matrix();
 
     /**
      * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
      * gray".
+     *
+     * Instead of scanning every pixel in the bitmap, we first resize the bitmap to no more than
+     * COMPACT_BITMAP_SIZE^2 pixels using filtering. The hope is that any non-gray color elements
+     * will survive the squeezing process, contaminating the result with color.
      */
     public boolean isGrayscale(Bitmap bitmap) {
-        final int height = bitmap.getHeight();
-        final int width = bitmap.getWidth();
-        int size = height*width;
+        int height = bitmap.getHeight();
+        int width = bitmap.getWidth();
 
+        // shrink to a more manageable (yet hopefully no more or less colorful) size
+        if (height > COMPACT_BITMAP_SIZE || width > COMPACT_BITMAP_SIZE) {
+            if (mTempCompactBitmap == null) {
+                mTempCompactBitmap = Bitmap.createBitmap(
+                        COMPACT_BITMAP_SIZE, COMPACT_BITMAP_SIZE, Bitmap.Config.ARGB_8888
+                );
+                mTempCompactBitmapCanvas = new Canvas(mTempCompactBitmap);
+                mTempCompactBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+                mTempCompactBitmapPaint.setFilterBitmap(true);
+            }
+            mTempMatrix.reset();
+            mTempMatrix.setScale(
+                    (float) COMPACT_BITMAP_SIZE / width,
+                    (float) COMPACT_BITMAP_SIZE / height,
+                    0, 0);
+            mTempCompactBitmapCanvas.drawColor(0, PorterDuff.Mode.SRC); // select all, erase
+            mTempCompactBitmapCanvas.drawBitmap(bitmap, mTempMatrix, mTempCompactBitmapPaint);
+            bitmap = mTempCompactBitmap;
+            width = height = COMPACT_BITMAP_SIZE;
+        }
+
+        final int size = height*width;
         ensureBufferSize(size);
         bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height);
         for (int i = 0; i < size; i++) {
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 665055c..3249ea3 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -50,23 +50,36 @@
     private final WeakHashMap<Bitmap, Pair<Boolean, Integer>> mGrayscaleBitmapCache =
             new WeakHashMap<Bitmap, Pair<Boolean, Integer>>();
 
-    public static NotificationColorUtil getInstance() {
+    private final int mGrayscaleIconMaxSize; // @dimen/notification_large_icon_width (64dp)
+
+    public static NotificationColorUtil getInstance(Context context) {
         synchronized (sLock) {
             if (sInstance == null) {
-                sInstance = new NotificationColorUtil();
+                sInstance = new NotificationColorUtil(context);
             }
             return sInstance;
         }
     }
 
+    private NotificationColorUtil(Context context) {
+        mGrayscaleIconMaxSize = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_large_icon_width);
+    }
+
     /**
-     * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
-     * gray".
+     * Checks whether a Bitmap is a small grayscale icon.
+     * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
      *
      * @param bitmap The bitmap to test.
-     * @return Whether the bitmap is grayscale.
+     * @return True if the bitmap is grayscale; false if it is color or too large to examine.
      */
-    public boolean isGrayscale(Bitmap bitmap) {
+    public boolean isGrayscaleIcon(Bitmap bitmap) {
+        // quick test: reject large bitmaps
+        if (bitmap.getWidth() > mGrayscaleIconMaxSize
+                || bitmap.getHeight() > mGrayscaleIconMaxSize) {
+            return false;
+        }
+
         synchronized (sLock) {
             Pair<Boolean, Integer> cached = mGrayscaleBitmapCache.get(bitmap);
             if (cached != null) {
@@ -92,22 +105,22 @@
     }
 
     /**
-     * Checks whether a drawable is grayscale. Grayscale here means "very close to a perfect
-     * gray".
+     * Checks whether a Drawable is a small grayscale icon.
+     * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
      *
      * @param d The drawable to test.
-     * @return Whether the drawable is grayscale.
+     * @return True if the bitmap is grayscale; false if it is color or too large to examine.
      */
-    public boolean isGrayscale(Drawable d) {
+    public boolean isGrayscaleIcon(Drawable d) {
         if (d == null) {
             return false;
         } else if (d instanceof BitmapDrawable) {
             BitmapDrawable bd = (BitmapDrawable) d;
-            return bd.getBitmap() != null && isGrayscale(bd.getBitmap());
+            return bd.getBitmap() != null && isGrayscaleIcon(bd.getBitmap());
         } else if (d instanceof AnimationDrawable) {
             AnimationDrawable ad = (AnimationDrawable) d;
             int count = ad.getNumberOfFrames();
-            return count > 0 && isGrayscale(ad.getFrame(0));
+            return count > 0 && isGrayscaleIcon(ad.getFrame(0));
         } else if (d instanceof VectorDrawable) {
             // We just assume you're doing the right thing if using vectors
             return true;
@@ -117,16 +130,16 @@
     }
 
     /**
-     * Checks whether a drawable with a resoure id is grayscale. Grayscale here means "very close
-     * to a perfect gray".
+     * Checks whether a drawable with a resoure id is a small grayscale icon.
+     * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
      *
      * @param context The context to load the drawable from.
-     * @return Whether the drawable is grayscale.
+     * @return True if the bitmap is grayscale; false if it is color or too large to examine.
      */
-    public boolean isGrayscale(Context context, int drawableResId) {
+    public boolean isGrayscaleIcon(Context context, int drawableResId) {
         if (drawableResId != 0) {
             try {
-                return isGrayscale(context.getDrawable(drawableResId));
+                return isGrayscaleIcon(context.getDrawable(drawableResId));
             } catch (Resources.NotFoundException ex) {
                 Log.e(TAG, "Drawable not found: " + drawableResId);
                 return false;
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 99babac..6ec6b00 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -291,10 +291,10 @@
     return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
 }
 
-static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
         jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->destroyCanvasAndSurface();
+    proxy->destroy();
 }
 
 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
@@ -430,7 +430,7 @@
     { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
-    { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
+    { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
     { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 423e250..2778b6e 100644
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -34,4 +34,11 @@
     </string-array>
 
     <bool name="config_auto_attach_data_on_creation">false</bool>
+
+    <!-- Values for GPS configuration (Verizon) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>LPP_PROFILE=3</item>
+        <item>GPS_LOCK=3</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc120/config.xml b/core/res/res/values-mcc310-mnc120/config.xml
index 62001d9..3b95db5 100644
--- a/core/res/res/values-mcc310-mnc120/config.xml
+++ b/core/res/res/values-mcc310-mnc120/config.xml
@@ -25,4 +25,10 @@
     -->
     <integer name="config_mobile_mtu">1422</integer>
 
+    <!-- Values for GPS configuration (Sprint) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>GPS_LOCK=3</item>
+        <item>LPP_PROFILE=2</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc150/config.xml b/core/res/res/values-mcc310-mnc150/config.xml
index f1936f4..00d2db8 100644
--- a/core/res/res/values-mcc310-mnc150/config.xml
+++ b/core/res/res/values-mcc310-mnc150/config.xml
@@ -33,4 +33,10 @@
         <item>315</item>
         <item>316</item>
     </string-array>
+    <!-- Values for GPS configuration (AT&T) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x33</item>
+        <item>LPP_PROFILE=3</item>
+        <item>GPS_LOCK=1</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 00cdaeb..2f9394a 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -25,9 +25,10 @@
     -->
     <integer name="config_mobile_mtu">1440</integer>
 
-    <!-- Values for GPS configuration -->
+    <!-- Values for GPS configuration (T-Mobile) -->
     <string-array translatable="false" name="config_gpsParameters">
-        <item>"SUPL_PORT=7279"</item>
+        <item>CAPABILITEIS=0x33</item>
         <item>GPS_LOCK=1</item>
+        <item>LPP_PROFILE=2</item>
     </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index 9e63047..8069d13 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -40,8 +40,10 @@
         <item>315</item>
         <item>316</item>
     </string-array>
-    <!-- Values for GPS configuration -->
+    <!-- Values for GPS configuration (AT&T) -->
     <string-array translatable="false" name="config_gpsParameters">
-        <item>"SUPL_HOST=supl.google.com"</item>
+        <item>CAPABILITIES=0x33</item>
+        <item>GPS_LOCK=1</item>
+        <item>LPP_PROFILE=3</item>
     </string-array>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc190/config.xml b/core/res/res/values-mcc311-mnc190/config.xml
index a6c4d1b..b4e436d 100644
--- a/core/res/res/values-mcc311-mnc190/config.xml
+++ b/core/res/res/values-mcc311-mnc190/config.xml
@@ -37,4 +37,11 @@
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string translatable="false" name="config_tether_apndata">Tether,broadband.cellular1.net,,,,,,,,,311,190,,DUN</string>
 
+    <!-- Values for GPS configuration (Sprint) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>GPS_LOCK=3</item>
+        <item>LPP_PROFILE=2</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index e5af60b..cd5d55b 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -44,4 +44,11 @@
     <bool name="config_mobile_allow_volte_vt">false</bool>
 
     <bool name="config_auto_attach_data_on_creation">false</bool>
+
+    <!-- Values for GPS configuration (Verizon) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>GPS_LOCK=3</item>
+        <item>LPP_PROFILE=3</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9b1b7ed..3628355 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1726,6 +1726,34 @@
         <enum name="KEYCODE_LAST_CHANNEL" value="229" />
         <enum name="KEYCODE_TV_DATA_SERVICE" value="230" />
         <enum name="KEYCODE_VOICE_ASSIST" value="231" />
+        <enum name="KEYCODE_TV_RADIO_SERVICE" value="232" />
+        <enum name="KEYCODE_TV_TELETEXT" value="233" />
+        <enum name="KEYCODE_TV_NUMBER_ENTRY" value="234" />
+        <enum name="KEYCODE_TV_TERRESTRIAL_ANALOG" value="235" />
+        <enum name="KEYCODE_TV_TERRESTRIAL_DIGITAL" value="236" />
+        <enum name="KEYCODE_TV_SATELLITE" value="237" />
+        <enum name="KEYCODE_TV_SATELLITE_BS" value="238" />
+        <enum name="KEYCODE_TV_SATELLITE_CS" value="239" />
+        <enum name="KEYCODE_TV_SATELLITE_SERVICE" value="240" />
+        <enum name="KEYCODE_TV_NETWORK" value="241" />
+        <enum name="KEYCODE_TV_ANTENNA_CABLE" value="242" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_1" value="243" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_2" value="244" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_3" value="245" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_4" value="246" />
+        <enum name="KEYCODE_TV_INPUT_COMPOSITE_1" value="247" />
+        <enum name="KEYCODE_TV_INPUT_COMPOSITE_2" value="248" />
+        <enum name="KEYCODE_TV_INPUT_COMPONENT_1" value="249" />
+        <enum name="KEYCODE_TV_INPUT_COMPONENT_2" value="250" />
+        <enum name="KEYCODE_TV_INPUT_VGA_1" value="251" />
+        <enum name="KEYCODE_TV_AUDIO_DESCRIPTION" value="252" />
+        <enum name="KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP" value="253" />
+        <enum name="KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN" value="254" />
+        <enum name="KEYCODE_TV_ZOOM_MODE" value="255" />
+        <enum name="KEYCODE_TV_CONTENTS_MENU" value="256" />
+        <enum name="KEYCODE_TV_MEDIA_CONTEXT_MENU" value="257" />
+        <enum name="KEYCODE_TV_TIMER_PROGRAMMING" value="258" />
+        <enum name="KEYCODE_HELP" value="259" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/docs/html/wear/images/partners/sony.png b/docs/html/wear/images/partners/sony.png
new file mode 100644
index 0000000..3e9483e
--- /dev/null
+++ b/docs/html/wear/images/partners/sony.png
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index 5dd7690..c9a5cff 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -228,6 +228,10 @@
             <div class="col-4">
               <img src="/wear/images/partners/samsung.png" alt="Samsung">
             </div>
+            <div class="col-4">
+              <img src="/wear/images/partners/sony.png" alt="Sony"
+                   style="margin-left:57px;margin-top:17px;">
+            </div>
           </div>
         </div> <!-- end .wrap -->
       </div>
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index ab43e01..4e68a60 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -37,10 +37,8 @@
  */
 class RippleBackground {
     private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
-    private static final TimeInterpolator DECEL_INTERPOLATOR = new LogInterpolator();
 
     private static final float GLOBAL_SPEED = 1.0f;
-    private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0f * GLOBAL_SPEED;
     private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0f / GLOBAL_SPEED;
     private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MAX = 4.5f * GLOBAL_SPEED;
     private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MIN = 1.5f * GLOBAL_SPEED;
@@ -70,11 +68,6 @@
     /** Screen density used to adjust pixel-based velocities. */
     private float mDensity;
 
-    private float mStartingX;
-    private float mStartingY;
-    private float mClampedStartingX;
-    private float mClampedStartingY;
-
     // Hardware rendering properties.
     private CanvasProperty<Paint> mPropOuterPaint;
     private CanvasProperty<Float> mPropOuterRadius;
@@ -83,8 +76,6 @@
 
     // Software animators.
     private ObjectAnimator mAnimOuterOpacity;
-    private ObjectAnimator mAnimX;
-    private ObjectAnimator mAnimY;
 
     // Temporary paint used for creating canvas properties.
     private Paint mTempPaint;
@@ -94,10 +85,6 @@
     private float mOuterX;
     private float mOuterY;
 
-    // Values used to tween between the start and end positions.
-    private float mTweenX = 0;
-    private float mTweenY = 0;
-
     /** Whether we should be drawing hardware animations. */
     private boolean mHardwareAnimating;
 
@@ -110,12 +97,9 @@
     /**
      * Creates a new ripple.
      */
-    public RippleBackground(RippleDrawable owner, Rect bounds, float startingX, float startingY) {
+    public RippleBackground(RippleDrawable owner, Rect bounds) {
         mOwner = owner;
         mBounds = bounds;
-
-        mStartingX = startingX;
-        mStartingY = startingY;
     }
 
     public void setup(int maxRadius, int color, float density) {
@@ -133,25 +117,6 @@
         mOuterX = 0;
         mOuterY = 0;
         mDensity = density;
-
-        clampStartingPosition();
-    }
-
-    private void clampStartingPosition() {
-        final float cX = mBounds.exactCenterX();
-        final float cY = mBounds.exactCenterY();
-        final float dX = mStartingX - cX;
-        final float dY = mStartingY - cY;
-        final float r = mOuterRadius;
-        if (dX * dX + dY * dY > r * r) {
-            // Point is outside the circle, clamp to the circumference.
-            final double angle = Math.atan2(dY, dX);
-            mClampedStartingX = cX + (float) (Math.cos(angle) * r);
-            mClampedStartingY = cY + (float) (Math.sin(angle) * r);
-        } else {
-            mClampedStartingX = mStartingX;
-            mClampedStartingY = mStartingY;
-        }
     }
 
     public void onHotspotBoundsChanged() {
@@ -159,8 +124,6 @@
             final float halfWidth = mBounds.width() / 2.0f;
             final float halfHeight = mBounds.height() / 2.0f;
             mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight);
-
-            clampStartingPosition();
         }
     }
 
@@ -175,28 +138,6 @@
         return mOuterOpacity;
     }
 
-    @SuppressWarnings("unused")
-    public void setXGravity(float x) {
-        mTweenX = x;
-        invalidateSelf();
-    }
-
-    @SuppressWarnings("unused")
-    public float getXGravity() {
-        return mTweenX;
-    }
-
-    @SuppressWarnings("unused")
-    public void setYGravity(float y) {
-        mTweenY = y;
-        invalidateSelf();
-    }
-
-    @SuppressWarnings("unused")
-    public float getYGravity() {
-        return mTweenY;
-    }
-
     /**
      * Draws the ripple centered at (0,0) using the specified paint.
      */
@@ -270,53 +211,23 @@
     }
 
     /**
-     * Specifies the starting position relative to the drawable bounds. No-op if
-     * the ripple has already entered.
-     */
-    public void move(float x, float y) {
-        mStartingX = x;
-        mStartingY = y;
-
-        clampStartingPosition();
-    }
-
-    /**
      * Starts the enter animation.
      */
     public void enter() {
         cancel();
 
-        final int radiusDuration = (int)
-                (1000 * Math.sqrt(mOuterRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5);
         final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_ENTER_VELOCITY);
-
-        final ObjectAnimator cX = ObjectAnimator.ofFloat(this, "xGravity", 1);
-        cX.setAutoCancel(true);
-        cX.setDuration(radiusDuration);
-        cX.setInterpolator(LINEAR_INTERPOLATOR);
-        cX.setStartDelay(RIPPLE_ENTER_DELAY);
-
-        final ObjectAnimator cY = ObjectAnimator.ofFloat(this, "yGravity", 1);
-        cY.setAutoCancel(true);
-        cY.setDuration(radiusDuration);
-        cY.setInterpolator(LINEAR_INTERPOLATOR);
-        cY.setStartDelay(RIPPLE_ENTER_DELAY);
-
         final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1);
         outer.setAutoCancel(true);
         outer.setDuration(outerDuration);
         outer.setInterpolator(LINEAR_INTERPOLATOR);
 
         mAnimOuterOpacity = outer;
-        mAnimX = cX;
-        mAnimY = cY;
 
         // Enter animations always run on the UI thread, since it's unlikely
         // that anything interesting is happening until the user lifts their
         // finger.
         outer.start();
-        cX.start();
-        cY.start();
     }
 
     /**
@@ -352,12 +263,6 @@
     private void exitHardware(int opacityDuration, int outerInflection, int inflectionOpacity) {
         mPendingAnimations.clear();
 
-        // TODO: Adjust background by starting position.
-        final float startX = MathUtils.lerp(
-                mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
-        final float startY = MathUtils.lerp(
-                mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
-
         final Paint outerPaint = getTempPaint();
         outerPaint.setAntiAlias(true);
         outerPaint.setColor(mColor);
@@ -422,14 +327,6 @@
         if (mAnimOuterOpacity != null) {
             mAnimOuterOpacity.end();
         }
-
-        if (mAnimX != null) {
-            mAnimX.end();
-        }
-
-        if (mAnimY != null) {
-            mAnimY.end();
-        }
     }
 
     private void endHardwareAnimations() {
@@ -457,16 +354,6 @@
     }
 
     private void exitSoftware(int opacityDuration, int outerInflection, int inflectionOpacity) {
-        final ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity", 1);
-        xAnim.setAutoCancel(true);
-        xAnim.setDuration(opacityDuration);
-        xAnim.setInterpolator(DECEL_INTERPOLATOR);
-
-        final ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity", 1);
-        yAnim.setAutoCancel(true);
-        yAnim.setDuration(opacityDuration);
-        yAnim.setInterpolator(DECEL_INTERPOLATOR);
-
         final ObjectAnimator outerOpacityAnim;
         if (outerInflection > 0) {
             // Outer opacity continues to increase for a bit.
@@ -510,12 +397,8 @@
         }
 
         mAnimOuterOpacity = outerOpacityAnim;
-        mAnimX = xAnim;
-        mAnimY = yAnim;
 
         outerOpacityAnim.start();
-        xAnim.start();
-        yAnim.start();
     }
 
     /**
@@ -531,14 +414,6 @@
         if (mAnimOuterOpacity != null) {
             mAnimOuterOpacity.cancel();
         }
-
-        if (mAnimX != null) {
-            mAnimX.cancel();
-        }
-
-        if (mAnimY != null) {
-            mAnimY.cancel();
-        }
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index e87a114..fa762b7 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -248,15 +248,14 @@
         boolean pressed = false;
         boolean focused = false;
 
-        final int N = stateSet.length;
-        for (int i = 0; i < N; i++) {
-            if (stateSet[i] == R.attr.state_enabled) {
+        for (int state : stateSet) {
+            if (state == R.attr.state_enabled) {
                 enabled = true;
             }
-            if (stateSet[i] == R.attr.state_focused) {
+            if (state == R.attr.state_focused) {
                 focused = true;
             }
-            if (stateSet[i] == R.attr.state_pressed) {
+            if (state == R.attr.state_pressed) {
                 pressed = true;
             }
         }
@@ -478,10 +477,6 @@
         if (mRipple != null) {
             mRipple.move(x, y);
         }
-
-        if (mBackground != null) {
-            mBackground.move(x, y);
-        }
     }
 
     /**
@@ -489,17 +484,7 @@
      */
     private void tryBackgroundEnter() {
         if (mBackground == null) {
-            final float x;
-            final float y;
-            if (mHasPending) {
-                mHasPending = false;
-                x = mPendingX;
-                y = mPendingY;
-            } else {
-                x = mHotspotBounds.exactCenterX();
-                y = mHotspotBounds.exactCenterY();
-            }
-            mBackground = new RippleBackground(this, mHotspotBounds, x, y);
+            mBackground = new RippleBackground(this, mHotspotBounds);
         }
 
         final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 5689e17..9855f71 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -24,6 +24,7 @@
 #include "Properties.h"
 #include "LayerRenderer.h"
 #include "ShadowTessellator.h"
+#include "RenderState.h"
 
 namespace android {
 
@@ -49,7 +50,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Caches::Caches(): Singleton<Caches>(),
-        mExtensions(Extensions::getInstance()), mInitialized(false) {
+        mExtensions(Extensions::getInstance()), mInitialized(false), mRenderState(NULL) {
     init();
     initFont();
     initConstraints();
@@ -267,8 +268,11 @@
     log.appendFormat("Current memory usage / total memory usage (bytes):\n");
     log.appendFormat("  TextureCache         %8d / %8d\n",
             textureCache.getSize(), textureCache.getMaxSize());
-    log.appendFormat("  LayerCache           %8d / %8d\n",
-            layerCache.getSize(), layerCache.getMaxSize());
+    log.appendFormat("  LayerCache           %8d / %8d (numLayers = %zu)\n",
+            layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
+    log.appendFormat("  Garbage layers       %8zu\n", mLayerGarbage.size());
+    log.appendFormat("  Active layers        %8zu\n",
+            mRenderState ? mRenderState->mActiveLayers.size() : 0);
     log.appendFormat("  RenderBufferCache    %8d / %8d\n",
             renderBufferCache.getSize(), renderBufferCache.getMaxSize());
     log.appendFormat("  GradientCache        %8d / %8d\n",
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 0482430..726b74d 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -107,6 +107,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 class RenderNode;
+class RenderState;
 
 class ANDROID_API Caches: public Singleton<Caches> {
     Caches();
@@ -132,6 +133,8 @@
      */
     bool initProperties();
 
+    void setRenderState(RenderState* renderState) { mRenderState = renderState; }
+
     /**
      * Flush the cache.
      *
@@ -431,6 +434,8 @@
     GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
 
     OverdrawColorSet mOverdrawDebugColorSet;
+
+    RenderState* mRenderState;
 }; // class Caches
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 13869aa..efa30ac 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -49,6 +49,10 @@
 // Size management
 ///////////////////////////////////////////////////////////////////////////////
 
+size_t LayerCache::getCount() {
+    return mCache.size();
+}
+
 uint32_t LayerCache::getSize() {
     return mSize;
 }
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index 1b0fc2c..6b93e8f 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -87,6 +87,8 @@
      */
     uint32_t getSize();
 
+    size_t getCount();
+
     /**
      * Prints out the content of the cache.
      */
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index 50b8f39..9948b44 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -32,10 +32,14 @@
     // This is delayed because the first access of Caches makes GL calls
     mCaches = &Caches::getInstance();
     mCaches->init();
+    mCaches->setRenderState(this);
 }
 
 void RenderState::onGLContextDestroyed() {
-    LOG_ALWAYS_FATAL_IF(!mActiveLayers.empty(), "layers have survived gl context destruction");
+    if (CC_UNLIKELY(!mActiveLayers.empty())) {
+        mCaches->dumpMemoryUsage();
+        LOG_ALWAYS_FATAL("layers have survived gl context destruction");
+    }
 }
 
 void RenderState::setViewport(GLsizei width, GLsizei height) {
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index cd71c73..3915fb5 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -59,6 +59,7 @@
 
 private:
     friend class renderthread::RenderThread;
+    friend class Caches;
 
     void interruptForFunctorInvoke();
     void resumeFromFunctorInvoke();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 0a17e13..967cb6f 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -51,13 +51,14 @@
 }
 
 CanvasContext::~CanvasContext() {
-    destroyCanvasAndSurface();
-    mRenderThread.removeFrameCallback(this);
+    destroy();
     delete mAnimationContext;
-    freePrefetechedLayers();
 }
 
-void CanvasContext::destroyCanvasAndSurface() {
+void CanvasContext::destroy() {
+    stopDrawing();
+    freePrefetechedLayers();
+    destroyHardwareResources();
     if (mCanvas) {
         delete mCanvas;
         mCanvas = 0;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 7c27190..5984fd0 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -66,7 +66,7 @@
     void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
     void prepareTree(TreeInfo& info);
     void draw();
-    void destroyCanvasAndSurface();
+    void destroy();
 
     // IFrameCallback, Chroreographer-driven frame callback entry point
     virtual void doFrame();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 3d04316..9528874 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -194,13 +194,13 @@
     return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
 }
 
-CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
-    args->context->destroyCanvasAndSurface();
+CREATE_BRIDGE1(destroy, CanvasContext* context) {
+    args->context->destroy();
     return NULL;
 }
 
-void RenderProxy::destroyCanvasAndSurface() {
-    SETUP_TASK(destroyCanvasAndSurface);
+void RenderProxy::destroy() {
+    SETUP_TASK(destroy);
     args->context = mContext;
     // destroyCanvasAndSurface() needs a fence as when it returns the
     // underlying BufferQueue is going to be released from under
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 9e6bcf5..8b8d99c 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -73,7 +73,7 @@
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
             float density);
-    ANDROID_API void destroyCanvasAndSurface();
+    ANDROID_API void destroy();
 
     ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
 
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1861bd7..f37cbe5 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1286,7 +1286,7 @@
 
     public int write(short[] audioData, int offsetInShorts, int sizeInShorts) {
 
-        if (mState == STATE_UNINITIALIZED || mAudioFormat != AudioFormat.ENCODING_PCM_16BIT) {
+        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
             return ERROR_INVALID_OPERATION;
         }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2da3b27..1c6dc2c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -648,7 +648,7 @@
                         @Override
                         public void onUserSwitchComplete(int newUserId) throws RemoteException {
                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
-                                    newUserId));
+                                    newUserId, 0));
                             mSwitchingUser = false;
                         }
                     });
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 761d58a..30b9629 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -33,7 +33,7 @@
 
         <Spinner
             android:id="@+id/destination_spinner"
-            android:layout_width="wrap_content"
+            android:layout_width="@dimen/preview_destination_spinner_width"
             android:layout_height="wrap_content"
             android:layout_marginTop="4dip"
             android:dropDownWidth="wrap_content"
diff --git a/packages/PrintSpooler/res/values-sw600dp-land/constants.xml b/packages/PrintSpooler/res/values-sw600dp-land/constants.xml
index f60d8e4..f7f8a18 100644
--- a/packages/PrintSpooler/res/values-sw600dp-land/constants.xml
+++ b/packages/PrintSpooler/res/values-sw600dp-land/constants.xml
@@ -17,6 +17,9 @@
 <resources>
 
     <integer name="print_option_column_count">6</integer>
+
     <integer name="preview_page_per_row_count">4</integer>
 
+    <dimen name="preview_destination_spinner_width">256dip</dimen>
+
 </resources>
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index b4e4777..357d3e1 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -45,4 +45,6 @@
     <dimen name="preview_page_footer_height">32dip</dimen>
     <dimen name="preview_page_min_width">128dip</dimen>
 
+    <dimen name="preview_destination_spinner_width">192dip</dimen>
+
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index cd2ccbd..06cba21 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -451,6 +451,8 @@
         @GuardedBy("mLock")
         private IPdfRenderer mRenderer;
 
+        private boolean mBoundToService;
+
         public AsyncRenderer(Context context, OnMalformedPdfFileListener malformedPdfFileListener) {
             mContext = context;
             mOnMalformedPdfFileListener = malformedPdfFileListener;
@@ -463,6 +465,7 @@
 
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
+            mBoundToService = true;
             synchronized (mLock) {
                 mRenderer = IPdfRenderer.Stub.asInterface(service);
                 mLock.notifyAll();
@@ -559,7 +562,10 @@
 
                 @Override
                 public void onPostExecute(Void result) {
-                    mContext.unbindService(AsyncRenderer.this);
+                    if (mBoundToService) {
+                        mBoundToService = false;
+                        mContext.unbindService(AsyncRenderer.this);
+                    }
                     mPageContentCache.invalidate();
                     mPageContentCache.clear();
                 }
diff --git a/packages/SystemUI/res/drawable/ic_info.xml b/packages/SystemUI/res/drawable/ic_info.xml
new file mode 100644
index 0000000..65e7bf5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_info.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index ac8af1b..d52c274 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -77,13 +77,23 @@
         </LinearLayout>
 
         <ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
+                 android:id="@+id/notification_inspect_app_provided_settings"
+                 android:layout_width="52dp"
+                 android:layout_height="match_parent"
+                 android:layout_weight="0"
+                 android:gravity="center"
+                 android:src="@drawable/ic_settings"
+                 android:visibility="gone"
+                />
+
+        <ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
                 android:id="@+id/notification_inspect_item"
                 android:layout_width="52dp"
                 android:layout_height="match_parent"
                 android:layout_weight="0"
                 android:gravity="center"
                 android:contentDescription="@string/status_bar_notification_inspect_item_title"
-                android:src="@drawable/ic_settings"
+                android:src="@drawable/ic_info"
                 />
     </LinearLayout>
 </com.android.systemui.statusbar.NotificationGuts>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 946914b..8cd4ce6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -289,13 +289,13 @@
     <dimen name="speed_bump_height">16dp</dimen>
 
     <!-- Lockscreen unlocking falsing threshold. -->
-    <dimen name="unlock_falsing_threshold">100dp</dimen>
+    <dimen name="unlock_falsing_threshold">80dp</dimen>
 
     <!-- Lockscreen falsing threshold for quick settings. -->
-    <dimen name="qs_falsing_threshold">60dp</dimen>
+    <dimen name="qs_falsing_threshold">80dp</dimen>
 
     <!-- Falsing threshold used when dismissing notifications from the lockscreen. -->
-    <dimen name="swipe_helper_falsing_threshold">100dp</dimen>
+    <dimen name="swipe_helper_falsing_threshold">70dp</dimen>
 
     <dimen name="notifications_top_padding">8dp</dimen>
     
@@ -315,7 +315,7 @@
     <dimen name="heads_up_window_height">250dp</dimen>
 
     <!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
-    <dimen name="keyguard_min_swipe_amount">85dp</dimen>
+    <dimen name="keyguard_min_swipe_amount">90dp</dimen>
 
     <!-- The minimum background radius when swiping to a side for the camera / phone affordances. -->
     <dimen name="keyguard_affordance_min_background_radius">30dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b488c56..c7a91af 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -522,9 +522,13 @@
     <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_clear_all">Clear all notifications.</string>
 
-    <!-- Title shown in notification popup for inspecting the responsible
-         application [CHAR LIMIT=30] -->
-    <string name="status_bar_notification_inspect_item_title">Settings</string>
+    <!-- Content description of button in notification inspector for system settings relating to
+         notifications from this application [CHAR LIMIT=NONE] -->
+    <string name="status_bar_notification_inspect_item_title">Notification settings</string>
+
+    <!-- Content description of button in notification inspetor for application-provided settings
+         for its own notifications [CHAR LIMIT=NONE] -->
+    <string name="status_bar_notification_app_settings_title"><xliff:g id="app_name" example="Calendar">%s</xliff:g> settings</string>
 
     <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is on. [CHAR LIMIT=NONE] -->
     <string name="accessibility_rotation_lock_off">Screen will rotate automatically.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 54c2c09..f8d0d9e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -27,6 +27,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.UserInfo;
 import android.media.AudioManager;
 import android.media.SoundPool;
 import android.os.Bundle;
@@ -302,6 +303,13 @@
         @Override
         public void onUserSwitchComplete(int userId) {
             mSwitchingUser = false;
+            if (userId != UserHandle.USER_OWNER) {
+                UserInfo info = UserManager.get(mContext).getUserInfo(userId);
+                if (info != null && info.isGuest()) {
+                    // If we just switched to a guest, try to dismiss keyguard.
+                    dismiss();
+                }
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ce29407..2c1d70d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -34,13 +34,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Build;
@@ -96,6 +94,7 @@
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
@@ -177,7 +176,7 @@
     // public mode, private notifications, etc
     private boolean mLockscreenPublicMode = false;
     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
-    private NotificationColorUtil mNotificationColorUtil = NotificationColorUtil.getInstance();
+    private NotificationColorUtil mNotificationColorUtil;
 
     private UserManager mUserManager;
 
@@ -435,6 +434,8 @@
         mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
 
+        mNotificationColorUtil = NotificationColorUtil.getInstance(mContext);
+
         mNotificationData = new NotificationData(this);
 
         mDreamManager = IDreamManager.Stub.asInterface(
@@ -717,11 +718,23 @@
                entry.expandedBig.findViewById(com.android.internal.R.id.media_actions) != null;
     }
 
+    // The gear button in the guts that links to the app's own notification settings
+    private void startAppOwnNotificationSettingsActivity(Intent intent,
+            final int notificationId, final String notificationTag, final int appUid) {
+        intent.putExtra("notification_id", notificationId);
+        intent.putExtra("notification_tag", notificationTag);
+        startNotificationGutsIntent(intent, appUid);
+    }
+
+    // The (i) button in the guts that links to the system notification settings for that app
     private void startAppNotificationSettingsActivity(String packageName, final int appUid) {
         final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
         intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+        startNotificationGutsIntent(intent, appUid);
+    }
 
+    private void startNotificationGutsIntent(final Intent intent, final int appUid) {
         final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
         dismissKeyguardThenExecute(new OnDismissAction() {
             @Override
@@ -1128,7 +1141,7 @@
                 entry.notification.getUser().getIdentifier());
 
         int maxHeight = mRowMaxHeight;
-        StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.notification;
         RemoteViews contentView = sbn.getNotification().contentView;
         RemoteViews bigContentView = sbn.getNotification().bigContentView;
 
@@ -1197,6 +1210,8 @@
         ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(entry.notification.getPostTime());
         ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
         final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
+        final View appSettingsButton
+                = guts.findViewById(R.id.notification_inspect_app_provided_settings);
         if (appUid >= 0) {
             final int appUidF = appUid;
             settingsButton.setOnClickListener(new View.OnClickListener() {
@@ -1204,8 +1219,33 @@
                     startAppNotificationSettingsActivity(pkg, appUidF);
                 }
             });
+
+            final Intent appSettingsQueryIntent
+                    = new Intent(Intent.ACTION_MAIN)
+                        .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
+                        .setPackage(pkg);
+            List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
+            if (infos.size() > 0) {
+                appSettingsButton.setVisibility(View.VISIBLE);
+                appSettingsButton.setContentDescription(
+                        mContext.getResources().getString(
+                                R.string.status_bar_notification_app_settings_title,
+                                appname
+                        ));
+                final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
+                        .setClassName(pkg, infos.get(0).activityInfo.name);
+                appSettingsButton.setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
+                                sbn.getId(),
+                                sbn.getTag(),
+                                appUidF);
+                    }
+                });
+            }
         } else {
             settingsButton.setVisibility(View.GONE);
+            appSettingsButton.setVisibility(View.GONE);
         }
 
         workAroundBadLayerDrawableOpacity(row);
@@ -1281,7 +1321,9 @@
             // Add a basic notification template
             publicViewLocal = LayoutInflater.from(mContext).inflate(
                     com.android.internal.R.layout.notification_template_material_base,
-                    expandedPublic, true);
+                    expandedPublic, false);
+            publicViewLocal.setIsRootNamespace(true);
+            expandedPublic.setContractedChild(publicViewLocal);
 
             final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
             try {
@@ -1305,7 +1347,7 @@
 
             Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
             icon.setImageDrawable(iconDrawable);
-            if (mNotificationColorUtil.isGrayscale(iconDrawable)) {
+            if (mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
                 icon.setBackgroundResource(
                         com.android.internal.R.drawable.notification_icon_legacy_bg);
                 int padding = mContext.getResources().getDimensionPixelSize(
@@ -1902,6 +1944,13 @@
     }
 
     protected boolean shouldInterrupt(StatusBarNotification sbn) {
+        if (mNotificationData.shouldFilterOut(sbn)) {
+            if (DEBUG) {
+                Log.d(TAG, "Skipping HUN check for " + sbn.getKey() + " since it's filtered out.");
+            }
+            return false;
+        }
+
         Notification notification = sbn.getNotification();
         // some predicates to make the boolean logic legible
         boolean isNoisy = (notification.defaults & Notification.DEFAULT_SOUND) != 0
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index dfcc408..e3a0b18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -17,10 +17,15 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
+import android.widget.ImageView;
 import com.android.systemui.R;
 
 public class ExpandableNotificationRow extends ActivatableNotificationView {
@@ -62,6 +67,51 @@
     private boolean mWasReset;
     private NotificationGuts mGuts;
 
+    public void setIconAnimationRunning(boolean running) {
+        setIconAnimationRunning(running, mPublicLayout);
+        setIconAnimationRunning(running, mPrivateLayout);
+    }
+
+    private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
+        if (layout != null) {
+            View contractedChild = layout.getContractedChild();
+            View expandedChild = layout.getExpandedChild();
+            setIconAnimationRunningForChild(running, contractedChild);
+            setIconAnimationRunningForChild(running, expandedChild);
+        }
+    }
+
+    private void setIconAnimationRunningForChild(boolean running, View child) {
+        if (child != null) {
+            ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
+            setIconRunning(icon, running);
+            ImageView rightIcon = (ImageView) child.findViewById(
+                    com.android.internal.R.id.right_icon);
+            setIconRunning(rightIcon, running);
+        }
+    }
+
+    private void setIconRunning(ImageView imageView, boolean running) {
+        if (imageView != null) {
+            Drawable drawable = imageView.getDrawable();
+            if (drawable instanceof AnimationDrawable) {
+                AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
+                if (running) {
+                    animationDrawable.start();
+                } else {
+                    animationDrawable.stop();
+                }
+            } else if (drawable instanceof AnimatedVectorDrawable) {
+                AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
+                if (running) {
+                    animationDrawable.start();
+                } else {
+                    animationDrawable.stop();
+                }
+            }
+        }
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 5878ae1..a4161f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -251,15 +251,19 @@
     }
 
     public void setCircleRadius(float circleRadius) {
-        setCircleRadius(circleRadius, false);
+        setCircleRadius(circleRadius, false, false);
+    }
+
+    public void setCircleRadius(float circleRadius, boolean slowAnimation) {
+        setCircleRadius(circleRadius, slowAnimation, false);
     }
 
     public void setCircleRadiusWithoutAnimation(float circleRadius) {
         cancelAnimator(mCircleAnimator);
-        setCircleRadius(circleRadius, true);
+        setCircleRadius(circleRadius, false ,true);
     }
 
-    private void setCircleRadius(float circleRadius, boolean noAnimation) {
+    private void setCircleRadius(float circleRadius, boolean slowAnimation, boolean noAnimation) {
 
         // Check if we need a new animation
         boolean radiusHidden = (mCircleAnimator != null && mCircleWillBeHidden)
@@ -292,10 +296,13 @@
                     ? mDisappearInterpolator
                     : mAppearInterpolator;
             animator.setInterpolator(interpolator);
-            float durationFactor = Math.abs(mCircleRadius - circleRadius)
-                    / (float) mMinBackgroundRadius;
-            long duration = (long) (CIRCLE_APPEAR_DURATION * durationFactor);
-            duration = Math.min(duration, CIRCLE_DISAPPEAR_MAX_DURATION);
+            long duration = 250;
+            if (!slowAnimation) {
+                float durationFactor = Math.abs(mCircleRadius - circleRadius)
+                        / (float) mMinBackgroundRadius;
+                duration = (long) (CIRCLE_APPEAR_DURATION * durationFactor);
+                duration = Math.min(duration, CIRCLE_DISAPPEAR_MAX_DURATION);
+            }
             animator.setDuration(duration);
             animator.start();
             if (mPreviewView != null && mPreviewView.getVisibility() == View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 8b4c2c4..e31eb7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -88,6 +88,14 @@
         mContractedVisible = true;
     }
 
+    public View getContractedChild() {
+        return mContractedChild;
+    }
+
+    public View getExpandedChild() {
+        return mExpandedChild;
+    }
+
     public void setContractedChild(View child) {
         if (mContractedChild != null) {
             mContractedChild.animate().cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 454041c..cef889c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -221,7 +221,7 @@
         return mGroupsWithSummaries.contains(groupKey);
     }
 
-    private boolean shouldFilterOut(StatusBarNotification sbn) {
+    boolean shouldFilterOut(StatusBarNotification sbn) {
         if (!(mEnvironment.isDeviceProvisioned() ||
                 showNotificationEvenIfUnprovisioned(sbn))) {
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
index c75bd28..c4c9dac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -36,7 +36,7 @@
     private TextView mMoreText;
     private int mTintColor;
     private int mIconSize;
-    private NotificationColorUtil mNotificationColorUtil = new NotificationColorUtil();
+    private NotificationColorUtil mNotificationColorUtil;
 
     public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -45,6 +45,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mNotificationColorUtil = NotificationColorUtil.getInstance(getContext());
         mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
         mIconSize = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_icon_size);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index eca8e6a..a9c701a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -20,8 +20,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.os.PowerManager;
-import android.os.SystemClock;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -85,9 +83,9 @@
         mContext = context;
         mCallback = callback;
         initIcons();
-        updateIcon(mLeftIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false);
-        updateIcon(mCenterIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false);
-        updateIcon(mRightIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false);
+        updateIcon(mLeftIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false);
+        updateIcon(mCenterIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false);
+        updateIcon(mRightIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false);
         initDimens();
     }
 
@@ -295,8 +293,7 @@
         float vel = getCurrentVelocity();
 
         // We snap back if the current translation is not far enough
-        boolean snapBack = Math.abs(mTranslation) < Math.abs(mTranslationOnDown)
-                + mMinTranslationAmount;
+        boolean snapBack = isBelowFalsingThreshold();
 
         // or if the velocity is in the opposite direction.
         boolean velIsInWrongDirection = vel * mTranslation < 0;
@@ -305,6 +302,11 @@
         fling(vel, snapBack || forceSnapBack);
     }
 
+    private boolean isBelowFalsingThreshold() {
+        return Math.abs(mTranslation) < Math.abs(mTranslationOnDown)
+                + mMinTranslationAmount;
+    }
+
     private void fling(float vel, final boolean snapBack) {
         float target = mTranslation < 0 ? -mCallback.getPageWidth() : mCallback.getPageWidth();
         target = snapBack ? 0 : target;
@@ -355,13 +357,14 @@
 
             boolean animateIcons = isReset && animateReset;
             float radius = getRadiusFromTranslation(absTranslation);
+            boolean slowAnimation = isReset && isBelowFalsingThreshold();
             if (!isReset) {
-                updateIcon(targetView, radius, alpha, false);
+                updateIcon(targetView, radius, alpha, false, false);
             } else {
-                updateIcon(targetView, 0.0f, fadeOutAlpha, animateIcons);
+                updateIcon(targetView, 0.0f, fadeOutAlpha, animateIcons, slowAnimation);
             }
-            updateIcon(otherView, 0.0f, fadeOutAlpha, animateIcons);
-            updateIcon(mCenterIcon, 0.0f, fadeOutAlpha, animateIcons);
+            updateIcon(otherView, 0.0f, fadeOutAlpha, animateIcons, slowAnimation);
+            updateIcon(mCenterIcon, 0.0f, fadeOutAlpha, animateIcons, slowAnimation);
 
             mTranslation = translation;
         }
@@ -392,16 +395,16 @@
     }
 
     public void animateHideLeftRightIcon() {
-        updateIcon(mRightIcon, 0f, 0f, true);
-        updateIcon(mLeftIcon, 0f, 0f, true);
+        updateIcon(mRightIcon, 0f, 0f, true, false);
+        updateIcon(mLeftIcon, 0f, 0f, true, false);
     }
 
     private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha,
-            boolean animate) {
+            boolean animate, boolean slowRadiusAnimation) {
         if (view.getVisibility() != View.VISIBLE) {
             return;
         }
-        view.setCircleRadius(circleRadius);
+        view.setCircleRadius(circleRadius, slowRadiusAnimation);
         updateIconAlpha(view, alpha, animate);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 91a8b22..bae1864 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -548,7 +548,7 @@
     }
 
     private boolean flingExpandsQs(float vel) {
-        if (!mQsTouchAboveFalsingThreshold && mStatusBarState == StatusBarState.KEYGUARD) {
+        if (isBelowFalsingThreshold()) {
             return false;
         }
         if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -558,6 +558,10 @@
         }
     }
 
+    private boolean isBelowFalsingThreshold() {
+        return !mQsTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded();
+    }
+
     private float getQsExpansionFraction() {
         return Math.min(1f, (mQsExpansionHeight - mQsMinExpansionHeight)
                 / (getTempQsMaxExpansion() - mQsMinExpansionHeight));
@@ -1122,9 +1126,16 @@
             }
             return;
         }
+        boolean belowFalsingThreshold = isBelowFalsingThreshold();
+        if (belowFalsingThreshold) {
+            vel = 0;
+        }
         mScrollView.setBlockFlinging(true);
         ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
         mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
+        if (belowFalsingThreshold) {
+            animator.setDuration(350);
+        }
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
@@ -1692,9 +1703,9 @@
     }
 
     public void setEmptyDragAmount(float amount) {
-        float factor = 1f;
+        float factor = 0.8f;
         if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
-            factor = 0.6f;
+            factor = 0.4f;
         } else if (!mStatusBar.hasActiveNotifications()) {
             factor = 0.4f;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 6127811..7261ea1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -479,7 +479,7 @@
      * @return whether a fling should expands the panel; contracts otherwise
      */
     protected boolean flingExpands(float vel, float vectorVel) {
-        if (!mTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded()) {
+        if (isBelowFalsingThreshold()) {
             return true;
         }
         if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -489,6 +489,10 @@
         }
     }
 
+    private boolean isBelowFalsingThreshold() {
+        return !mTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded();
+    }
+
     protected void fling(float vel, boolean expand) {
         cancelPeek();
         float target = expand ? getMaxPanelHeight() : 0.0f;
@@ -509,7 +513,14 @@
         mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
         ValueAnimator animator = createHeightAnimator(target);
         if (expand) {
+            boolean belowFalsingThreshold = isBelowFalsingThreshold();
+            if (belowFalsingThreshold) {
+                vel = 0;
+            }
             mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
+            if (belowFalsingThreshold) {
+                animator.setDuration(350);
+            }
         } else {
             mFlingAnimationUtils.applyDismissing(animator, mExpandedHeight, target, vel,
                     getHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 148b00c..fed579c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1467,6 +1467,7 @@
             // drawn when removed
             getOverlay().add(child);
         }
+        updateAnimationState(false, child);
 
         // Make sure the clipRect we might have set is removed
         child.setClipBounds(null);
@@ -1545,10 +1546,28 @@
         mStackScrollAlgorithm.notifyChildrenChanged(this);
         ((ExpandableView) child).setOnHeightChangedListener(this);
         generateAddAnimation(child, false /* fromMoreCard */);
+        updateAnimationState(mAnimationsEnabled && mIsExpanded, child);
     }
 
     public void setAnimationsEnabled(boolean animationsEnabled) {
         mAnimationsEnabled = animationsEnabled;
+        updateNotificationAnimationStates();
+    }
+
+    private void updateNotificationAnimationStates() {
+        boolean running = mIsExpanded && mAnimationsEnabled;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            updateAnimationState(running, child);
+        }
+    }
+
+    private void updateAnimationState(boolean running, View child) {
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            row.setIconAnimationRunning(running);
+        }
     }
 
     public boolean isAddOrRemoveAnimationPending() {
@@ -1918,8 +1937,12 @@
     }
 
     private void setIsExpanded(boolean isExpanded) {
+        boolean changed = isExpanded != mIsExpanded;
         mIsExpanded = isExpanded;
         mStackScrollAlgorithm.setIsExpanded(isExpanded);
+        if (changed) {
+            updateNotificationAnimationStates();
+        }
     }
 
     @Override
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 3e7a7e4..083aa9b 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -8395,10 +8395,15 @@
 
         Slog.i(TAG, "Auto restore => " + doAutoRestore);
 
-        synchronized (this) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.BACKUP_AUTO_RESTORE, doAutoRestore ? 1 : 0);
-            mAutoRestore = doAutoRestore;
+        final long oldId = Binder.clearCallingIdentity();
+        try {
+            synchronized (this) {
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.BACKUP_AUTO_RESTORE, doAutoRestore ? 1 : 0);
+                mAutoRestore = doAutoRestore;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(oldId);
         }
     }
 
@@ -8467,10 +8472,15 @@
         synchronized (mTransports) {
             String prevTransport = null;
             if (mTransports.get(transport) != null) {
-                prevTransport = mCurrentTransport;
-                mCurrentTransport = transport;
-                Settings.Secure.putString(mContext.getContentResolver(),
-                        Settings.Secure.BACKUP_TRANSPORT, transport);
+                final long oldId = Binder.clearCallingIdentity();
+                try {
+                    prevTransport = mCurrentTransport;
+                    mCurrentTransport = transport;
+                    Settings.Secure.putString(mContext.getContentResolver(),
+                            Settings.Secure.BACKUP_TRANSPORT, transport);
+                } finally {
+                    Binder.restoreCallingIdentity(oldId);
+                }
                 Slog.v(TAG, "selectBackupTransport() set " + mCurrentTransport
                         + " returning " + prevTransport);
             } else {
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 2830b5e..65ad1ce 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -192,29 +192,30 @@
     // Service API calls implementation, proxied to the real MmsService in "com.android.mms.service"
     private final class BinderService extends IMms.Stub {
         @Override
-        public void sendMessage(long subId, String callingPkg, byte[] pdu, String locationUrl,
-                ContentValues configOverrides, PendingIntent sentIntent) throws RemoteException {
+        public void sendMessage(long subId, String callingPkg, Uri contentUri,
+                String locationUrl, ContentValues configOverrides, PendingIntent sentIntent)
+                        throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
                 return;
             }
-            getServiceGuarded().sendMessage(subId, callingPkg, pdu, locationUrl, configOverrides,
-                    sentIntent);
+            getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
+                    configOverrides, sentIntent);
         }
 
         @Override
         public void downloadMessage(long subId, String callingPkg, String locationUrl,
-                ContentValues configOverrides, PendingIntent downloadedIntent)
-                throws RemoteException {
+                Uri contentUri, ContentValues configOverrides,
+                PendingIntent downloadedIntent) throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
                     "Download MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
                 return;
             }
-            getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, configOverrides,
-                    downloadedIntent);
+            getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
+                    configOverrides, downloadedIntent);
         }
 
         @Override
@@ -249,8 +250,9 @@
         }
 
         @Override
-        public Uri importMultimediaMessage(String callingPkg, byte[] pdu, String messageId,
-                long timestampSecs, boolean seen, boolean read) throws RemoteException {
+        public Uri importMultimediaMessage(String callingPkg, Uri contentUri,
+                String messageId, long timestampSecs, boolean seen, boolean read)
+                        throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Import MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
@@ -259,7 +261,7 @@
                 return FAKE_MMS_SENT_URI;
             }
             return getServiceGuarded().importMultimediaMessage(
-                    callingPkg, pdu, messageId, timestampSecs, seen, read);
+                    callingPkg, contentUri, messageId, timestampSecs, seen, read);
         }
 
         @Override
@@ -317,7 +319,8 @@
         }
 
         @Override
-        public Uri addMultimediaMessageDraft(String callingPkg, byte[] pdu) throws RemoteException {
+        public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
+                throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Add MMS draft");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
@@ -325,7 +328,7 @@
                 // while writing the TelephonyProvider
                 return FAKE_MMS_DRAFT_URI;
             }
-            return getServiceGuarded().addMultimediaMessageDraft(callingPkg, pdu);
+            return getServiceGuarded().addMultimediaMessageDraft(callingPkg, contentUri);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 008ec99..2e9df8a 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8408,6 +8408,10 @@
         synchronized(this) {
             TaskRecord tr = recentTaskForIdLocked(taskId);
             if (tr != null) {
+                if (tr == mStackSupervisor.mLockTaskModeTask) {
+                    mStackSupervisor.showLockTaskToast();
+                    return;
+                }
                 if (DEBUG_STACK) Slog.d(TAG, "moveTaskToBack: moving task=" + tr);
                 ActivityStack stack = tr.stack;
                 if (stack.mResumedActivity != null && stack.mResumedActivity.task == tr) {
@@ -8440,11 +8444,19 @@
         enforceNotIsolatedCaller("moveActivityTaskToBack");
         synchronized(this) {
             final long origId = Binder.clearCallingIdentity();
-            int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
-            if (taskId >= 0) {
-                return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId, null);
+            try {
+                int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
+                if (taskId >= 0) {
+                    if ((mStackSupervisor.mLockTaskModeTask != null)
+                            && (mStackSupervisor.mLockTaskModeTask.taskId == taskId)) {
+                        mStackSupervisor.showLockTaskToast();
+                        return false;
+                    }
+                    return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId, null);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(origId);
             }
-            Binder.restoreCallingIdentity(origId);
         }
         return false;
     }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6bc1c9c..780efa1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1262,7 +1262,7 @@
         if (err == ActivityManager.START_SUCCESS) {
             final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
             Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
-                    + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)
+                    + "} from uid " + callingUid
                     + " on display " + (container == null ? (mFocusedStack == null ?
                             Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) :
                             (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
@@ -2075,6 +2075,7 @@
             }
             targetStack = inTask.stack;
             targetStack.moveTaskToFrontLocked(inTask, r, options);
+            targetStack.moveToFront();
             mWindowManager.moveTaskToTop(inTask.taskId);
 
             // Check whether we should actually launch the new activity in to the task,
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index cedf573..ff319d3 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -16,6 +16,7 @@
 
 package com.android.server.connectivity;
 
+import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -213,6 +214,7 @@
     private final NetworkAgentInfo mNetworkAgentInfo;
     private final TelephonyManager mTelephonyManager;
     private final WifiManager mWifiManager;
+    private final AlarmManager mAlarmManager;
 
     private String mServer;
     private boolean mIsCaptivePortalCheckEnabled = false;
@@ -236,6 +238,7 @@
         mNetworkAgentInfo = networkAgentInfo;
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 
         addState(mDefaultState);
         addState(mOfflineState, mDefaultState);
@@ -500,10 +503,38 @@
     }
 
     private class LingeringState extends State {
+        private static final String ACTION_LINGER_EXPIRED = "android.net.netmon.lingerExpired";
+        private static final String EXTRA_NETID = "lingerExpiredNetId";
+        private static final String EXTRA_TOKEN = "lingerExpiredToken";
+
+        private class LingerExpiredBroadcastReceiver extends BroadcastReceiver {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getAction().equals(ACTION_LINGER_EXPIRED) &&
+                        Integer.parseInt(intent.getStringExtra(EXTRA_NETID)) ==
+                        mNetworkAgentInfo.network.netId) {
+                    sendMessage(CMD_LINGER_EXPIRED,
+                            Integer.parseInt(intent.getStringExtra(EXTRA_TOKEN)));
+                }
+            }
+        }
+
+        private BroadcastReceiver mBroadcastReceiver;
+        private PendingIntent mIntent;
+
         @Override
         public void enter() {
-            Message message = obtainMessage(CMD_LINGER_EXPIRED, ++mLingerToken, 0);
-            sendMessageDelayed(message, mLingerDelayMs);
+            mBroadcastReceiver = new LingerExpiredBroadcastReceiver();
+            mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_LINGER_EXPIRED));
+
+            Intent intent = new Intent(ACTION_LINGER_EXPIRED, null);
+            intent.putExtra(EXTRA_NETID, String.valueOf(mNetworkAgentInfo.network.netId));
+            intent.putExtra(EXTRA_TOKEN, String.valueOf(++mLingerToken));
+            mIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+            long wakeupTime = SystemClock.elapsedRealtime() + mLingerDelayMs;
+            mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime,
+                    // Give a specific window so we aren't subject to unknown inexactitude.
+                    mLingerDelayMs / 6, mIntent);
         }
 
         @Override
@@ -524,6 +555,12 @@
                     return NOT_HANDLED;
             }
         }
+
+        @Override
+        public void exit() {
+            mAlarmManager.cancel(mIntent);
+            mContext.unregisterReceiver(mBroadcastReceiver);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 93c0f07..9314cf8 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -856,8 +856,11 @@
                 device.onDeviceRemoved();
                 // There is no explicit event for device removal unlike capability register event
                 // used for device addition . Hence we remove the device on hotplug event.
-                invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_REMOVE_DEVICE);
-                updateSafeMhlInput();
+                HdmiDeviceInfo deviceInfo = device.getInfo();
+                if (deviceInfo != null) {
+                    invokeDeviceEventListeners(deviceInfo, DEVICE_EVENT_REMOVE_DEVICE);
+                    updateSafeMhlInput();
+                }
             } else {
                 Slog.w(TAG, "No device to remove:[portId=" + portId);
             }
@@ -1082,7 +1085,7 @@
                         // the connected mobile device, start routing control to switch ports.
                         // callback is handled by MHL action.
                         device.turnOn(callback);
-                        tv.doManualPortSwitching(device.getInfo().getPortId(), null);
+                        tv.doManualPortSwitching(device.getPortId(), null);
                         return;
                     }
                     tv.deviceSelect(deviceId, callback);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c3bc306..30154d7 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -199,9 +199,6 @@
             List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
             for (int i=0; i<jobsForUser.size(); i++) {
                 JobStatus toRemove = jobsForUser.get(i);
-                if (DEBUG) {
-                    Slog.d(TAG, "Cancelling: " + toRemove);
-                }
                 cancelJobLocked(toRemove);
             }
         }
@@ -219,9 +216,6 @@
             List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
             for (int i=0; i<jobsForUid.size(); i++) {
                 JobStatus toRemove = jobsForUid.get(i);
-                if (DEBUG) {
-                    Slog.d(TAG, "Cancelling: " + toRemove);
-                }
                 cancelJobLocked(toRemove);
             }
         }
@@ -547,14 +541,28 @@
         private void queueReadyJobsForExecutionH() {
             synchronized (mJobs) {
                 ArraySet<JobStatus> jobs = mJobs.getJobs();
+                if (DEBUG) {
+                    Slog.d(TAG, "queuing all ready jobs for execution:");
+                }
                 for (int i=0; i<jobs.size(); i++) {
                     JobStatus job = jobs.valueAt(i);
                     if (isReadyToBeExecutedLocked(job)) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "    queued " + job.toShortString());
+                        }
                         mPendingJobs.add(job);
                     } else if (isReadyToBeCancelledLocked(job)) {
                         stopJobOnServiceContextLocked(job);
                     }
                 }
+                if (DEBUG) {
+                    final int queuedJobs = mPendingJobs.size();
+                    if (queuedJobs == 0) {
+                        Slog.d(TAG, "No jobs pending.");
+                    } else {
+                        Slog.d(TAG, queuedJobs + " jobs queued.");
+                    }
+                }
             }
         }
 
@@ -657,6 +665,9 @@
         private void maybeRunPendingJobsH() {
             synchronized (mJobs) {
                 Iterator<JobStatus> it = mPendingJobs.iterator();
+                if (DEBUG) {
+                    Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
+                }
                 while (it.hasNext()) {
                     JobStatus nextPending = it.next();
                     JobServiceContext availableContext = null;
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 5297911..344c57b 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -157,6 +157,7 @@
             mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
 
             mVerb = VERB_BINDING;
+            scheduleOpTimeOut();
             final Intent intent = new Intent().setComponent(job.getServiceComponent());
             boolean binding = mContext.bindServiceAsUser(intent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
@@ -253,8 +254,6 @@
             return;
         }
         this.service = IJobService.Stub.asInterface(service);
-        // Remove all timeouts.
-        mCallbackHandler.removeMessages(MSG_TIMEOUT);
         final PowerManager pm =
                 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mRunningJob.getTag());
@@ -299,6 +298,7 @@
         public void handleMessage(Message message) {
             switch (message.what) {
                 case MSG_SERVICE_BOUND:
+                    removeMessages(MSG_TIMEOUT);
                     handleServiceBoundH();
                     break;
                 case MSG_CALLBACK:
@@ -337,6 +337,9 @@
 
         /** Start the job on the service. */
         private void handleServiceBoundH() {
+            if (DEBUG) {
+                Slog.d(TAG, "MSG_SERVICE_BOUND for " + mRunningJob.toShortString());
+            }
             if (mVerb != VERB_BINDING) {
                 Slog.e(TAG, "Sending onStartJob for a job that isn't pending. "
                         + VERB_STRINGS[mVerb]);
@@ -456,42 +459,36 @@
 
         /** Process MSG_TIMEOUT here. */
         private void handleOpTimeoutH() {
-            if (JobSchedulerService.DEBUG) {
-                Slog.d(TAG, "MSG_TIMEOUT of " +
-                        mRunningJob.getServiceComponent().getShortClassName() + " : "
-                        + mParams.getJobId());
-            }
-
-            final int jobId = mParams.getJobId();
             switch (mVerb) {
+                case VERB_BINDING:
+                    Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
+                            ", dropping.");
+                    closeAndCleanupJobH(false /* needsReschedule */);
+                    break;
                 case VERB_STARTING:
                     // Client unresponsive - wedged or failed to respond in time. We don't really
                     // know what happened so let's log it and notify the JobScheduler
                     // FINISHED/NO-RETRY.
                     Slog.e(TAG, "No response from client for onStartJob '" +
-                            mRunningJob.getServiceComponent().getShortClassName() + "' jId: "
-                            + jobId);
+                            mRunningJob.toShortString());
                     closeAndCleanupJobH(false /* needsReschedule */);
                     break;
                 case VERB_STOPPING:
                     // At least we got somewhere, so fail but ask the JobScheduler to reschedule.
                     Slog.e(TAG, "No response from client for onStopJob, '" +
-                            mRunningJob.getServiceComponent().getShortClassName() + "' jId: "
-                            + jobId);
+                            mRunningJob.toShortString());
                     closeAndCleanupJobH(true /* needsReschedule */);
                     break;
                 case VERB_EXECUTING:
                     // Not an error - client ran out of time.
                     Slog.i(TAG, "Client timed out while executing (no jobFinished received)." +
-                            " sending onStop. "  +
-                            mRunningJob.getServiceComponent().getShortClassName() + "' jId: "
-                            + jobId);
+                            " sending onStop. "  + mRunningJob.toShortString());
                     sendStopMessageH();
                     break;
                 default:
-                    Slog.e(TAG, "Handling timeout for an unknown active job state: "
-                            + mRunningJob);
-                    return;
+                    Slog.e(TAG, "Handling timeout for an invalid job state: " +
+                            mRunningJob.toShortString() + ", dropping.");
+                    closeAndCleanupJobH(false /* needsReschedule */);
             }
         }
 
@@ -530,7 +527,9 @@
                 } catch (RemoteException e) {
                     // Whatever.
                 }
-                mWakeLock.release();
+                if (mWakeLock != null) {
+                    mWakeLock.release();
+                }
                 mContext.unbindService(JobServiceContext.this);
                 mWakeLock = null;
                 mRunningJob = null;
@@ -547,25 +546,25 @@
             removeMessages(MSG_SHUTDOWN_EXECUTION);
             mCompletedListener.onJobCompleted(completedJob, reschedule);
         }
+    }
 
-        /**
-         * Called when sending a message to the client, over whose execution we have no control. If
-         * we haven't received a response in a certain amount of time, we want to give up and carry
-         * on with life.
-         */
-        private void scheduleOpTimeOut() {
-            mCallbackHandler.removeMessages(MSG_TIMEOUT);
+    /**
+     * Called when sending a message to the client, over whose execution we have no control. If
+     * we haven't received a response in a certain amount of time, we want to give up and carry
+     * on with life.
+     */
+    private void scheduleOpTimeOut() {
+        mCallbackHandler.removeMessages(MSG_TIMEOUT);
 
-            final long timeoutMillis = (mVerb == VERB_EXECUTING) ?
-                    EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
-            if (DEBUG) {
-                Slog.d(TAG, "Scheduling time out for '" +
-                        mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
-                        mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
-            }
-            Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
-            mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
-            mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
+        final long timeoutMillis = (mVerb == VERB_EXECUTING) ?
+                EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
+        if (DEBUG) {
+            Slog.d(TAG, "Scheduling time out for '" +
+                    mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
+                    mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
         }
+        Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
+        mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
+        mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9554afa..5639234 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -317,6 +317,7 @@
     final Context mContext;
     final boolean mFactoryTest;
     final boolean mOnlyCore;
+    final boolean mLazyDexOpt;
     final DisplayMetrics mMetrics;
     final int mDefParseFlags;
     final String[] mSeparateProcesses;
@@ -1266,6 +1267,7 @@
         mContext = context;
         mFactoryTest = factoryTest;
         mOnlyCore = onlyCore;
+        mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
         mMetrics = new DisplayMetrics();
         mSettings = new Settings(context);
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
@@ -4451,13 +4453,12 @@
         if (pkgs != null) {
             // Filter out packages that aren't recently used.
             //
-            // The exception is first boot of a non-eng device, which
+            // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
             // should do a full dexopt.
-            boolean eng = "eng".equals(SystemProperties.get("ro.build.type"));
-            if (eng || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
+            if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
                 // TODO: add a property to control this?
                 long dexOptLRUThresholdInMinutes;
-                if (eng) {
+                if (mLazyDexOpt) {
                     dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
                 } else {
                     dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
@@ -4523,6 +4524,9 @@
     }
 
     public boolean performDexOpt(String packageName, String instructionSet, boolean updateUsage) {
+        if (!mLazyDexOpt) {
+            return false;
+        }
         PackageParser.Package p;
         final String targetInstructionSet;
         synchronized (mPackages) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 7e0215c..c8b5b3e 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -116,7 +116,7 @@
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
             mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
             mReceiver.register(mContext);
-            refreshAgentList();
+            refreshAgentList(UserHandle.USER_ALL);
         }
     }
 
@@ -157,11 +157,17 @@
         dispatchOnTrustChanged(aggregateIsTrusted(userId), userId, initiatedByUser);
     }
 
-    void refreshAgentList() {
+    void refreshAgentList(int userId) {
         if (DEBUG) Slog.d(TAG, "refreshAgentList()");
         PackageManager pm = mContext.getPackageManager();
 
-        List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+        List<UserInfo> userInfos;
+        if (userId == UserHandle.USER_ALL) {
+            userInfos = mUserManager.getUsers(true /* excludeDying */);
+        } else {
+            userInfos = new ArrayList<>();
+            userInfos.add(mUserManager.getUserInfo(userId));
+        }
         LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
 
         ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
@@ -170,6 +176,7 @@
         for (UserInfo userInfo : userInfos) {
             if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
                     == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
+            if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
             DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
             int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
             final boolean disableTrustAgents =
@@ -233,7 +240,7 @@
         }
     }
 
-    void updateDevicePolicyFeatures(int userId) {
+    void updateDevicePolicyFeatures() {
         for (int i = 0; i < mActiveAgents.size(); i++) {
             AgentInfo info = mActiveAgents.valueAt(i);
             if (info.agent.isConnected()) {
@@ -276,7 +283,7 @@
         if (trustMayHaveChanged) {
             updateTrust(userId, false);
         }
-        refreshAgentList();
+        refreshAgentList(userId);
     }
 
     private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
@@ -383,7 +390,7 @@
     private void updateUserHasAuthenticated(int userId) {
         if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
             mUserHasAuthenticatedSinceBoot.put(userId, true);
-            updateTrust(userId, false);
+            refreshAgentList(userId);
         }
     }
 
@@ -391,10 +398,10 @@
     private void requireCredentialEntry(int userId) {
         if (userId == UserHandle.USER_ALL) {
             mUserHasAuthenticatedSinceBoot.clear();
-            updateTrustAll();
+            refreshAgentList(UserHandle.USER_ALL);
         } else {
             mUserHasAuthenticatedSinceBoot.put(userId, false);
-            updateTrust(userId, false);
+            refreshAgentList(userId);
         }
     }
 
@@ -578,7 +585,7 @@
                     dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
                     break;
                 case MSG_ENABLED_AGENTS_CHANGED:
-                    refreshAgentList();
+                    refreshAgentList(UserHandle.USER_ALL);
                     break;
                 case MSG_REQUIRE_CREDENTIAL_ENTRY:
                     requireCredentialEntry(msg.arg1);
@@ -590,7 +597,7 @@
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
         @Override
         public void onSomePackagesChanged() {
-            refreshAgentList();
+            refreshAgentList(UserHandle.USER_ALL);
         }
 
         @Override
@@ -611,8 +618,8 @@
         public void onReceive(Context context, Intent intent) {
             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
                     intent.getAction())) {
-                refreshAgentList();
-                updateDevicePolicyFeatures(getSendingUserId());
+                refreshAgentList(getSendingUserId());
+                updateDevicePolicyFeatures();
             } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
                 updateUserHasAuthenticated(getSendingUserId());
             }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 564a3df..cad2772 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -40,7 +40,6 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -70,7 +69,6 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.security.Credentials;
-import android.security.IKeyChainService;
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
 import android.util.Log;
@@ -2749,7 +2747,8 @@
         return !"".equals(state);
     }
 
-    public boolean installCaCert(ComponentName who, byte[] certBuffer) throws RemoteException {
+    @Override
+    public void enforceCanManageCaCerts(ComponentName who) {
         if (who == null) {
             mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
         } else {
@@ -2757,6 +2756,11 @@
                 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             }
         }
+    }
+
+    @Override
+    public boolean installCaCert(ComponentName admin, byte[] certBuffer) throws RemoteException {
+        enforceCanManageCaCerts(admin);
 
         byte[] pemCert;
         try {
@@ -2791,21 +2795,15 @@
         return false;
     }
 
-    private static X509Certificate parseCert(byte[] certBuffer)
-            throws CertificateException, IOException {
+    private static X509Certificate parseCert(byte[] certBuffer) throws CertificateException {
         CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
         return (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(
                 certBuffer));
     }
 
-    public void uninstallCaCert(ComponentName who, String alias) {
-        if (who == null) {
-            mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
-        } else {
-            synchronized (this) {
-                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            }
-        }
+    @Override
+    public void uninstallCaCert(ComponentName admin, String alias) {
+        enforceCanManageCaCerts(admin);
 
         final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
         final long id = Binder.clearCallingIdentity();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 6e13732..a0b8c94 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -125,7 +125,8 @@
                 UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
         assertNotNull(userInfo1);
         assertNull(userInfo2);
-
+        // Verify that current user is not a managed profile
+        assertFalse(mUserManager.isManagedProfile());
         // Cleanup
         removeUser(userInfo1.id);
     }
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 7c596c1..5bf0855 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -347,14 +347,6 @@
         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
 
         /**
-         * Launches an activity for this connection on top of the in-call UI.
-         *
-         * @param call The {@code Call} invoking this method.
-         * @param intent The intent to use to start the activity.
-         */
-        public void onStartActivity(Call call, PendingIntent intent) {}
-
-        /**
          * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
          * up their UI for the {@code Call} in response to state transitions. Specifically,
          * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
@@ -753,11 +745,6 @@
     }
 
     /** {@hide} */
-    final void internalStartActivity(PendingIntent intent) {
-        fireStartActivity(intent);
-    }
-
-    /** {@hide} */
     final void internalSetDisconnected() {
         if (mState != Call.STATE_DISCONNECTED) {
             mState = Call.STATE_DISCONNECTED;
@@ -809,12 +796,6 @@
         }
     }
 
-    private void fireStartActivity(PendingIntent intent) {
-        for (Listener listener : mListeners) {
-            listener.onStartActivity(this, intent);
-        }
-    }
-
     private void fireCallDestroyed() {
         for (Listener listener : mListeners) {
             listener.onCallDestroyed(this);
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index f349659..4d6e267 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -81,7 +81,6 @@
                 Connection c, VideoProvider videoProvider) {}
         public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
         public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
-        public void onStartActivityFromInCall(Connection c, PendingIntent intent) {}
         public void onConferenceableConnectionsChanged(
                 Connection c, List<Connection> conferenceableConnections) {}
         public void onConferenceChanged(Connection c, Conference conference) {}
@@ -942,20 +941,6 @@
     }
 
     /**
-     * Launches an activity for this connection on top of the in-call UI.
-     *
-     * @param intent The intent to use to start the activity.
-     */
-    public final void startActivityFromInCall(PendingIntent intent) {
-        if (!intent.isActivity()) {
-            throw new IllegalArgumentException("Activity intent required.");
-        }
-        for (Listener l : mListeners) {
-            l.onStartActivityFromInCall(this, intent);
-        }
-    }
-
-    /**
      * Notifies this Connection that the {@link #getAudioState()} property has a new value.
      *
      * @param state The new call audio state.
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 19cf622..2dc6910 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -463,12 +463,6 @@
         }
 
         @Override
-        public void onStartActivityFromInCall(Connection c, PendingIntent intent) {
-            String id = mIdByConnection.get(c);
-            mAdapter.startActivityFromInCall(id, intent);
-        }
-
-        @Override
         public void onConferenceableConnectionsChanged(
                 Connection connection, List<Connection> conferenceableConnections) {
             mAdapter.setConferenceableConnections(
@@ -834,24 +828,6 @@
      */
     public void onConference(Connection connection1, Connection connection2) {}
 
-    /**
-     * Notifies that a connection has been added to this connection service and sent to Telecomm.
-     *
-     * @param connection The connection which was added.
-     */
-    public void onConnectionAdded(Connection connection) {}
-
-    /**
-     * Notified that a connection has been removed from this connection service.
-     * <p>
-     * TODO: Deprecate this since we can listen to the Connection onDestroyed() to determine when
-     * it is destroyed. This then percolates down to the RemoteConference stuff, where we can also
-     * have a callback for one being added, but we don't need one for being destroyed.
-     *
-     * @param connection The connection which was removed.
-     */
-    public void onConnectionRemoved(Connection connection) {}
-
     public void onRemoteConferenceAdded(RemoteConference conference) {}
 
     /**
@@ -879,7 +855,6 @@
         mIdByConnection.put(connection, callId);
         connection.addConnectionListener(mConnectionListener);
         connection.setConnectionService(this);
-        onConnectionAdded(connection);
     }
 
     private void removeConnection(Connection connection) {
@@ -888,7 +863,6 @@
         connection.removeConnectionListener(mConnectionListener);
         mConnectionById.remove(mIdByConnection.get(connection));
         mIdByConnection.remove(connection);
-        onConnectionRemoved(connection);
         mAdapter.removeCall(id);
     }
 
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index cb63646..e3dc713 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -346,13 +346,4 @@
             }
         }
     }
-
-    void startActivityFromInCall(String callId, PendingIntent intent) {
-        for (IConnectionServiceAdapter adapter : mAdapters) {
-            try {
-                adapter.startActivityFromInCall(callId, intent);
-            } catch (RemoteException e) {
-            }
-        }
-    }
 }
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
index 0e1c516..21e99db 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
@@ -57,8 +57,7 @@
     private static final int MSG_SET_STATUS_HINTS = 17;
     private static final int MSG_SET_HANDLE = 18;
     private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
-    private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 20;
-    private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 21;
+    private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
 
     private final IConnectionServiceAdapter mDelegate;
 
@@ -192,16 +191,6 @@
                     }
                     break;
                 }
-                case MSG_START_ACTIVITY_FROM_IN_CALL: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        mDelegate.startActivityFromInCall(
-                                (String) args.arg1, (PendingIntent) args.arg2);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                }
                 case MSG_SET_CONFERENCEABLE_CONNECTIONS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
@@ -352,14 +341,6 @@
         }
 
         @Override
-        public final void startActivityFromInCall(String connectionId, PendingIntent intent) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = connectionId;
-            args.arg2 = intent;
-            mHandler.obtainMessage(MSG_START_ACTIVITY_FROM_IN_CALL, args).sendToTarget();
-        }
-
-        @Override
         public final void setConferenceableConnections(
                 String connectionId, List<String> conferenceableConnectionIds) {
             SomeArgs args = SomeArgs.obtain();
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index 62a90bc..51cd537 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -55,7 +55,6 @@
     private static final int MSG_SET_POST_DIAL_WAIT = 4;
     private static final int MSG_ON_AUDIO_STATE_CHANGED = 5;
     private static final int MSG_BRING_TO_FOREGROUND = 6;
-    private static final int MSG_START_ACTIVITY = 7;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -89,15 +88,6 @@
                 case MSG_BRING_TO_FOREGROUND:
                     mPhone.internalBringToForeground(msg.arg1 == 1);
                     break;
-                case MSG_START_ACTIVITY:
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        mPhone.internalStartActivity(
-                                (String) args.arg1, (PendingIntent) args.arg2);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
                 default:
                     break;
             }
@@ -143,14 +133,6 @@
         public void bringToForeground(boolean showDialpad) {
             mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
         }
-
-        @Override
-        public void startActivity(String callId, PendingIntent intent) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = callId;
-            args.arg2 = intent;
-            mHandler.obtainMessage(MSG_START_ACTIVITY, args).sendToTarget();
-        }
     }
 
     private Phone mPhone;
diff --git a/telecomm/java/android/telecomm/Phone.java b/telecomm/java/android/telecomm/Phone.java
index d90d954..8831f8f 100644
--- a/telecomm/java/android/telecomm/Phone.java
+++ b/telecomm/java/android/telecomm/Phone.java
@@ -150,14 +150,6 @@
         fireBringToForeground(showDialpad);
     }
 
-    /** {@hide} */
-    final void internalStartActivity(String telecommId, PendingIntent intent) {
-        Call call = mCallByTelecommCallId.get(telecommId);
-        if (call != null) {
-            call.internalStartActivity(intent);
-        }
-    }
-
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      * @hide
diff --git a/telecomm/java/android/telecomm/PhoneAccount.java b/telecomm/java/android/telecomm/PhoneAccount.java
index 5b46409..1d61a6e 100644
--- a/telecomm/java/android/telecomm/PhoneAccount.java
+++ b/telecomm/java/android/telecomm/PhoneAccount.java
@@ -23,7 +23,12 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.MissingResourceException;
 
 /**
@@ -77,6 +82,21 @@
      */
     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
 
+    /**
+     * URI scheme for telephone number URIs.
+     */
+    public static final String SCHEME_TEL = "tel";
+
+    /**
+     * URI scheme for voicemail URIs.
+     */
+    public static final String SCHEME_VOICEMAIL = "voicemail";
+
+    /**
+     * URI scheme for SIP URIs.
+     */
+    public static final String SCHEME_SIP = "sip";
+
     private final PhoneAccountHandle mAccountHandle;
     private final Uri mHandle;
     private final String mSubscriptionNumber;
@@ -84,6 +104,7 @@
     private final int mIconResId;
     private final CharSequence mLabel;
     private final CharSequence mShortDescription;
+    private final List<String> mSupportedUriSchemes;
 
     public static class Builder {
         private PhoneAccountHandle mAccountHandle;
@@ -93,6 +114,7 @@
         private int mIconResId;
         private CharSequence mLabel;
         private CharSequence mShortDescription;
+        private List<String> mSupportedUriSchemes = new ArrayList<String>();
 
         public Builder() {}
 
@@ -131,7 +153,40 @@
             return this;
         }
 
+        /**
+         * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
+         *
+         * @param uriScheme The URI scheme.
+         * @return The Builder.
+         */
+        public Builder withSupportedUriScheme(String uriScheme) {
+            if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
+                this.mSupportedUriSchemes.add(uriScheme);
+            }
+            return this;
+        }
+
+        /**
+         * Specifies additional URI schemes supported by the {@link PhoneAccount}.
+         *
+         * @param uriSchemes The URI schemes.
+         * @return The Builder.
+         */
+        public Builder withSupportedUriSchemes(List<String> uriSchemes) {
+            if (uriSchemes != null && !uriSchemes.isEmpty()) {
+                for (String uriScheme : uriSchemes) {
+                    withSupportedUriScheme(uriScheme);
+                }
+            }
+            return this;
+        }
+
         public PhoneAccount build() {
+            // If no supported URI schemes were defined, assume "tel" is supported.
+            if (mSupportedUriSchemes.isEmpty()) {
+                withSupportedUriScheme(SCHEME_TEL);
+            }
+
             return new PhoneAccount(
                     mAccountHandle,
                     mHandle,
@@ -139,7 +194,8 @@
                     mCapabilities,
                     mIconResId,
                     mLabel,
-                    mShortDescription);
+                    mShortDescription,
+                    mSupportedUriSchemes);
         }
     }
 
@@ -150,7 +206,8 @@
             int capabilities,
             int iconResId,
             CharSequence label,
-            CharSequence shortDescription) {
+            CharSequence shortDescription,
+            List<String> supportedUriSchemes) {
         mAccountHandle = account;
         mHandle = handle;
         mSubscriptionNumber = subscriptionNumber;
@@ -158,6 +215,7 @@
         mIconResId = iconResId;
         mLabel = label;
         mShortDescription = shortDescription;
+        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
     }
 
     public static Builder builder() { return new Builder(); }
@@ -228,6 +286,36 @@
     }
 
     /**
+     * The URI schemes supported by this {@code PhoneAccount}.
+     *
+     * @return The URI schemes.
+     */
+    public List<String> getSupportedUriSchemes() {
+        return mSupportedUriSchemes;
+    }
+
+    /**
+     * Determines if the {@link PhoneAccount} supports calls to/from handles with a specified URI
+     * scheme.
+     *
+     * @param uriScheme The URI scheme to check.
+     * @return {@code True} if the {@code PhoneAccount} supports calls to/from handles with the
+     * specified URI scheme.
+     */
+    public boolean supportsUriScheme(String uriScheme) {
+        if (mSupportedUriSchemes == null || uriScheme == null) {
+            return false;
+        }
+
+        for (String scheme : mSupportedUriSchemes) {
+            if (scheme != null && scheme.equals(uriScheme)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * The icon resource ID for the icon of this {@code PhoneAccount}.
      *
      * @return A resource ID.
@@ -281,6 +369,7 @@
         out.writeInt(mIconResId);
         out.writeCharSequence(mLabel);
         out.writeCharSequence(mShortDescription);
+        out.writeList(mSupportedUriSchemes);
     }
 
     public static final Creator<PhoneAccount> CREATOR
@@ -297,6 +386,8 @@
     };
 
     private PhoneAccount(Parcel in) {
+        ClassLoader classLoader = PhoneAccount.class.getClassLoader();
+
         mAccountHandle = in.readParcelable(getClass().getClassLoader());
         mHandle = in.readParcelable(getClass().getClassLoader());
         mSubscriptionNumber = in.readString();
@@ -304,5 +395,9 @@
         mIconResId = in.readInt();
         mLabel = in.readCharSequence();
         mShortDescription = in.readCharSequence();
+
+        List<String> supportedUriSchemes = new ArrayList<>();
+        in.readList(supportedUriSchemes, classLoader);
+        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
     }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index b7e4b2a..31afb4b 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -163,16 +163,6 @@
         public void onVideoStateChanged(RemoteConnection connection, int videoState) {}
 
         /**
-         * Indicates that this {@code RemoteConnection} is requesting that the in-call UI
-         * launch the specified activity.
-         *
-         * @param connection The {@code RemoteConnection} invoking this method.
-         * @param intent A {@link PendingIntent} that the {@code RemoteConnection} wishes to
-         *         have launched on its behalf.
-         */
-        public void onStartActivityFromInCall(RemoteConnection connection, PendingIntent intent) {}
-
-        /**
          * Indicates that this {@code RemoteConnection} has been destroyed. No further requests
          * should be made to the {@code RemoteConnection}, and references to it should be cleared.
          *
@@ -729,13 +719,6 @@
     }
 
     /** @hide */
-    void startActivityFromInCall(PendingIntent intent) {
-        for (Listener l : mListeners) {
-            l.onStartActivityFromInCall(this, intent);
-        }
-    }
-
-    /** @hide */
     void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {
         mConferenceableConnections.clear();
         mConferenceableConnections.addAll(conferenceableConnections);
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 51722fe..0b6badb 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -261,12 +261,6 @@
         }
 
         @Override
-        public void startActivityFromInCall(String callId, PendingIntent intent) {
-            findConnectionForAction(callId, "startActivityFromInCall")
-                    .startActivityFromInCall(intent);
-        }
-
-        @Override
         public IBinder asBinder() {
             throw new UnsupportedOperationException();
         }
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index 2243288..071b719 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -258,8 +258,8 @@
 
     /**
      * Return the {@link PhoneAccount} which is the user-chosen default for making outgoing phone
-     * calls. This {@code PhoneAccount} will always be a member of the list which is returned from
-     * calling {@link #getEnabledPhoneAccounts()}.
+     * calls with a specified URI scheme. This {@code PhoneAccount} will always be a member of the
+     * list which is returned from calling {@link #getEnabledPhoneAccounts()}.
      * <p>
      * Apps must be prepared for this method to return {@code null}, indicating that there currently
      * exists no user-chosen default {@code PhoneAccount}. In this case, apps wishing to initiate a
@@ -272,11 +272,13 @@
      * {@code Intent} with no {@link TelecommManager#EXTRA_PHONE_ACCOUNT_HANDLE} is valid, and
      * subsequent steps in the phone call flow are responsible for presenting the user with an
      * affordance, if necessary, to choose a {@code PhoneAccount}.
+     *
+     * @param uriScheme The URI scheme.
      */
-    public PhoneAccountHandle getDefaultOutgoingPhoneAccount() {
+    public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
         try {
             if (isServiceConnected()) {
-                return getTelecommService().getDefaultOutgoingPhoneAccount();
+                return getTelecommService().getDefaultOutgoingPhoneAccount(uriScheme);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelecommService#getDefaultOutgoingPhoneAccount", e);
@@ -366,6 +368,29 @@
     }
 
     /**
+     * Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
+     * calls which support the specified URI scheme.
+     * <P>
+     * For example, invoking with {@code "tel"} will find all {@link PhoneAccountHandle}s which
+     * support telephone calls (e.g. URIs such as {@code tel:555-555-1212}).  Invoking with
+     * {@code "sip"} will find all {@link PhoneAccountHandle}s which support SIP calls (e.g. URIs
+     * such as {@code sip:example@sipexample.com}).
+     *
+     * @param uriScheme The URI scheme.
+     * @return A list of {@code PhoneAccountHandle} objects supporting the URI scheme.
+     */
+    public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
+        try {
+            if (isServiceConnected()) {
+                return getTelecommService().getPhoneAccountsSupportingScheme(uriScheme);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelecommService#getPhoneAccountsSupportingScheme", e);
+        }
+        return new ArrayList<>();
+    }
+
+    /**
      * Determine whether the device has more than one account registered and enabled.
      *
      * @return {@code true} if the device has more than one account registered and enabled and
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index ef1769f..610178e 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -76,6 +76,4 @@
     void setCallerDisplayName(String callId, String callerDisplayName, int presentation);
 
     void setConferenceableConnections(String callId, in List<String> conferenceableCallIds);
-
-    void startActivityFromInCall(String callId, in PendingIntent intent);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
index 5d4992f..23dbaf4 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
@@ -43,6 +43,4 @@
     void onAudioStateChanged(in AudioState audioState);
 
     void bringToForeground(boolean showDialpad);
-
-    void startActivity(String callId, in PendingIntent intent);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index 131307a..a6ab3ac 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -37,7 +37,7 @@
     /**
      * @see TelecommServiceImpl#getDefaultOutgoingPhoneAccount
      */
-    PhoneAccountHandle getDefaultOutgoingPhoneAccount();
+    PhoneAccountHandle getDefaultOutgoingPhoneAccount(in String uriScheme);
 
     /**
      * @see TelecommServiceImpl#setDefaultOutgoingPhoneAccount
@@ -50,7 +50,12 @@
     List<PhoneAccountHandle> getOutgoingPhoneAccounts();
 
     /**
-     * @see TelecommServiceImpl#getPhoneAccount
+     * @see TelecommManager#getPhoneAccountsSupportingScheme
+     */
+    List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme);
+
+    /**
+     * @see TelecommManager#getPhoneAccount
      */
     PhoneAccount getPhoneAccount(in PhoneAccountHandle account);
 
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index ced8e2f..55781fa 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -33,34 +33,33 @@
     public int mNameSource;
     public int mColor;
     public String mNumber;
-    public int mDispalyNumberFormat;
+    public int mDisplayNumberFormat;
     public int mDataRoaming;
     public int[] mSimIconRes;
 
     public SubInfoRecord() {
-        this.mSubId = -1;
+        this.mSubId = SubscriptionManager.INVALID_SUB_ID;
         this.mIccId = "";
-        this.mSlotId = -1;
+        this.mSlotId = SubscriptionManager.INVALID_SLOT_ID;
         this.mDisplayName = "";
         this.mNameSource = 0;
         this.mColor = 0;
         this.mNumber = "";
-        this.mDispalyNumberFormat = 0;
+        this.mDisplayNumberFormat = 0;
         this.mDataRoaming = 0;
         this.mSimIconRes = new int[2];
     }
 
-
-    public SubInfoRecord(long subId, String iccId, int slotId, String displayname, int nameSource,
-            int mColor, String mNumber, int displayFormat, int roaming, int[] iconRes) {
+    public SubInfoRecord(long subId, String iccId, int slotId, String displayName,
+            int nameSource, int mColor, String mNumber, int displayFormat, int roaming, int[] iconRes) {
         this.mSubId = subId;
         this.mIccId = iccId;
         this.mSlotId = slotId;
-        this.mDisplayName = displayname;
+        this.mDisplayName = displayName;
         this.mNameSource = nameSource;
         this.mColor = mColor;
         this.mNumber = mNumber;
-        this.mDispalyNumberFormat = displayFormat;
+        this.mDisplayNumberFormat = displayFormat;
         this.mDataRoaming = roaming;
         this.mSimIconRes = iconRes;
     }
@@ -74,13 +73,13 @@
             int mNameSource = source.readInt();
             int mColor = source.readInt();
             String mNumber = source.readString();
-            int mDispalyNumberFormat = source.readInt();
+            int mDisplayNumberFormat = source.readInt();
             int mDataRoaming = source.readInt();
             int[] iconRes = new int[2];
             source.readIntArray(iconRes);
 
             return new SubInfoRecord(mSubId, mIccId, mSlotId, mDisplayName, mNameSource, mColor, mNumber,
-                mDispalyNumberFormat, mDataRoaming, iconRes);
+                mDisplayNumberFormat, mDataRoaming, iconRes);
         }
 
         public SubInfoRecord[] newArray(int size) {
@@ -96,7 +95,7 @@
         dest.writeInt(mNameSource);
         dest.writeInt(mColor);
         dest.writeString(mNumber);
-        dest.writeInt(mDispalyNumberFormat);
+        dest.writeInt(mDisplayNumberFormat);
         dest.writeInt(mDataRoaming);
         dest.writeIntArray(mSimIconRes);
     }
@@ -109,7 +108,7 @@
         return "{mSubId=" + mSubId + ", mIccId=" + mIccId + " mSlotId=" + mSlotId
                 + " mDisplayName=" + mDisplayName + " mNameSource=" + mNameSource
                 + " mColor=" + mColor + " mNumber=" + mNumber
-                + " mDispalyNumberFormat=" + mDispalyNumberFormat + " mDataRoaming=" + mDataRoaming
+                + " mDisplayNumberFormat=" + mDisplayNumberFormat + " mDataRoaming=" + mDataRoaming
                 + " mSimIconRes=" + mSimIconRes + "}";
     }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 79e9fd5..f83f164 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -16,16 +16,9 @@
 
 package android.telephony;
 
-import static android.Manifest.permission.READ_PHONE_STATE;
-
-import android.app.ActivityManagerNative;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Intent;
-import android.database.Cursor;
-import android.os.UserHandle;
 import android.net.Uri;
 import android.provider.BaseColumns;
 import android.telephony.Rlog;
@@ -34,13 +27,7 @@
 
 import com.android.internal.telephony.ISub;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
-
-import java.util.ArrayList;
 import java.util.List;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map.Entry;
 
 /**
  *@hide
@@ -50,11 +37,26 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
-    // An invalid subscription identifier
-    public static final long INVALID_SUB_ID = Long.MAX_VALUE;
+    // An invalid phone identifier
+    public static final int INVALID_PHONE_ID = -1000;
 
-    // The default subscription identifier
-    public static final long DEFAULT_SUB_ID = Long.MAX_VALUE - 1;
+    // Indicates the caller wants the default phone id.
+    public static final int DEFAULT_PHONE_ID = Integer.MAX_VALUE;
+
+    // An invalid slot identifier
+    public static final int INVALID_SLOT_ID = -1000;
+
+    // Indicates the caller wants the default slot id.
+    public static final int DEFAULT_SLOT_ID = Integer.MAX_VALUE;
+
+    // An invalid subscription identifier
+    public static final long INVALID_SUB_ID = -1000;
+
+    // Indicates the user should be asked which sub to use.
+    public static final long ASK_USER_SUB_ID = -1001;
+
+    // Indicates the caller wants the default sub id.
+    public static final long DEFAULT_SUB_ID = Long.MAX_VALUE;
 
     public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
 
@@ -99,11 +101,13 @@
      */
     public static final String NAME_SOURCE = "name_source";
 
-    public static final int DEFAULT_SOURCE = 0;
+    public static final int NAME_SOURCE_UNDEFINDED = -1;
 
-    public static final int SIM_SOURCE = 1;
+    public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
 
-    public static final int USER_INPUT = 2;
+    public static final int NAME_SOURCE_SIM_SOURCE = 1;
+
+    public static final int NAME_SOURCE_USER_INPUT = 2;
 
     /**
      * The color of a SIM.
@@ -133,7 +137,7 @@
      */
     public static final String DISPLAY_NUMBER_FORMAT = "display_number_format";
 
-    public static final int DISPALY_NUMBER_NONE = 0;
+    public static final int DISPLAY_NUMBER_NONE = 0;
 
     public static final int DISPLAY_NUMBER_FIRST = 1;
 
@@ -159,9 +163,14 @@
 
     private static final int[] sSimBackgroundDarkRes = setSimResource(RES_TYPE_BACKGROUND_DARK);
 
-    private static final int[] sSimBackgroundLightRes = setSimResource(RES_TYPE_BACKGROUND_LIGHT);
-
-    private static HashMap<Integer, Long> mSimInfo = new HashMap<Integer, Long>();
+    /**
+     * Broadcast Action: The user has changed one of the default subs related to
+     * data, phone calls, or sms</p>
+     *
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String SUB_DEFAULT_CHANGED_ACTION =
+        "android.intent.action.SUB_DEFAULT_CHANGED";
 
     public SubscriptionManager() {
         if (DBG) logd("SubscriptionManager created");
@@ -169,14 +178,12 @@
 
     /**
      * Get the SubInfoRecord according to an index
-     * @param context Context provided by caller
      * @param subId The unique SubInfoRecord index in database
      * @return SubInfoRecord, maybe null
      */
-    public static SubInfoRecord getSubInfoUsingSubId(Context context, long subId) {
-        if (VDBG) logd("[getSubInfoUsingSubIdx]+ subId:" + subId);
-        if (subId <= 0) {
-            if (VDBG) logd("[getSubInfoUsingSubIdx]- subId <= 0");
+    public static SubInfoRecord getSubInfoUsingSubId(long subId) {
+        if (!isValidSubId(subId)) {
+            logd("[getSubInfoUsingSubIdx]- invalid subId");
             return null;
         }
 
@@ -197,11 +204,10 @@
 
     /**
      * Get the SubInfoRecord according to an IccId
-     * @param context Context provided by caller
      * @param iccId the IccId of SIM card
      * @return SubInfoRecord, maybe null
      */
-    public static List<SubInfoRecord> getSubInfoUsingIccId(Context context, String iccId) {
+    public static List<SubInfoRecord> getSubInfoUsingIccId(String iccId) {
         if (VDBG) logd("[getSubInfoUsingIccId]+ iccId=" + iccId);
         if (iccId == null) {
             logd("[getSubInfoUsingIccId]- null iccid");
@@ -224,14 +230,13 @@
 
     /**
      * Get the SubInfoRecord according to slotId
-     * @param context Context provided by caller
      * @param slotId the slot which the SIM is inserted
      * @return SubInfoRecord, maybe null
      */
-    public static List<SubInfoRecord> getSubInfoUsingSlotId(Context context, int slotId) {
-        if (VDBG) logd("[getSubInfoUsingSlotId]- slotId=" + slotId);
-        if (slotId < 0) {
-            logd("[getSubInfoUsingSlotId]- return null, slotId < 0");
+    public static List<SubInfoRecord> getSubInfoUsingSlotId(int slotId) {
+        // FIXME: Consider never returning null
+        if (!isValidSlotId(slotId)) {
+            logd("[getSubInfoUsingSlotId]- invalid slotId");
             return null;
         }
 
@@ -251,10 +256,9 @@
 
     /**
      * Get all the SubInfoRecord(s) in subinfo database
-     * @param context Context provided by caller
      * @return Array list of all SubInfoRecords in database, include thsoe that were inserted before
      */
-    public static List<SubInfoRecord> getAllSubInfoList(Context context) {
+    public static List<SubInfoRecord> getAllSubInfoList() {
         if (VDBG) logd("[getAllSubInfoList]+");
 
         List<SubInfoRecord> result = null;
@@ -273,18 +277,15 @@
 
     /**
      * Get the SubInfoRecord(s) of the currently inserted SIM(s)
-     * @param context Context provided by caller
      * @return Array list of currently inserted SubInfoRecord(s)
      */
-    public static List<SubInfoRecord> getActivatedSubInfoList(Context context) {
-        if (VDBG) logd("[getActivatedSubInfoList]+");
-
+    public static List<SubInfoRecord> getActiveSubInfoList() {
         List<SubInfoRecord> result = null;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                result = iSub.getActivatedSubInfoList();
+                result = iSub.getActiveSubInfoList();
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -295,10 +296,9 @@
 
     /**
      * Get the SUB count of all SUB(s) in subinfo database
-     * @param context Context provided by caller
      * @return all SIM count in database, include what was inserted before
      */
-    public static int getAllSubInfoCount(Context context) {
+    public static int getAllSubInfoCount() {
         if (VDBG) logd("[getAllSubInfoCount]+");
 
         int result = 0;
@@ -316,17 +316,38 @@
     }
 
     /**
+     * Get the count of active SUB(s)
+     * @return active SIM count
+     */
+    public static int getActiveSubInfoCount() {
+        int result = 0;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                result = iSub.getActiveSubInfoCount();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return result;
+    }
+
+    /**
      * Add a new SubInfoRecord to subinfo database if needed
-     * @param context Context provided by caller
      * @param iccId the IccId of the SIM card
      * @param slotId the slot which the SIM is inserted
      * @return the URL of the newly created row or the updated row
      */
-    public static Uri addSubInfoRecord(Context context, String iccId, int slotId) {
+    public static Uri addSubInfoRecord(String iccId, int slotId) {
         if (VDBG) logd("[addSubInfoRecord]+ iccId:" + iccId + " slotId:" + slotId);
         if (iccId == null) {
             logd("[addSubInfoRecord]- null iccId");
         }
+        if (!isValidSlotId(slotId)) {
+            logd("[addSubInfoRecord]- invalid slotId");
+        }
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -345,15 +366,14 @@
 
     /**
      * Set SIM color by simInfo index
-     * @param context Context provided by caller
      * @param color the color of the SIM
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
      */
-    public static int setColor(Context context, int color, long subId) {
+    public static int setColor(int color, long subId) {
         if (VDBG) logd("[setColor]+ color:" + color + " subId:" + subId);
         int size = sSimBackgroundDarkRes.length;
-        if (subId <= 0 || color < 0 || color >= size) {
+        if (!isValidSubId(subId) || color < 0 || color >= size) {
             logd("[setColor]- fail");
             return -1;
         }
@@ -375,26 +395,28 @@
 
     /**
      * Set display name by simInfo index
-     * @param context Context provided by caller
      * @param displayName the display name of SIM card
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
      */
-    public static int setDisplayName(Context context, String displayName, long subId) {
-        return setDisplayName(context, displayName, subId, -1);
+    public static int setDisplayName(String displayName, long subId) {
+        return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED);
     }
 
     /**
      * Set display name by simInfo index with name source
-     * @param context Context provided by caller
      * @param displayName the display name of SIM card
      * @param subId the unique SubInfoRecord index in database
-     * @param nameSource, 0: DEFAULT_SOURCE, 1: SIM_SOURCE, 2: USER_INPUT
-     * @return the number of records updated
+     * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
+     *                   2: NAME_SOURCE_USER_INPUT, -1 NAME_SOURCE_UNDEFINED
+     * @return the number of records updated or -1 if invalid subId
      */
-    public static int setDisplayName(Context context, String displayName, long subId, long nameSource) {
-        if (VDBG) logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId + " nameSource:" + nameSource);
-        if (subId <= 0) {
+    public static int setDisplayName(String displayName, long subId, long nameSource) {
+        if (VDBG) {
+            logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
+                    + " nameSource:" + nameSource);
+        }
+        if (!isValidSubId(subId)) {
             logd("[setDisplayName]- fail");
             return -1;
         }
@@ -416,15 +438,13 @@
 
     /**
      * Set phone number by subId
-     * @param context Context provided by caller
      * @param number the phone number of the SIM
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
      */
-    public static int setDispalyNumber(Context context, String number, long subId) {
-        if (VDBG) logd("[setDispalyNumber]+ number:" + number + " subId:" + subId);
-        if (number == null || subId <= 0) {
-            logd("[setDispalyNumber]- fail");
+    public static int setDisplayNumber(String number, long subId) {
+        if (number == null || !isValidSubId(subId)) {
+            logd("[setDisplayNumber]- fail");
             return -1;
         }
 
@@ -433,7 +453,7 @@
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                result = iSub.setDispalyNumber(number, subId);
+                result = iSub.setDisplayNumber(number, subId);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -445,14 +465,13 @@
 
     /**
      * Set number display format. 0: none, 1: the first four digits, 2: the last four digits
-     * @param context Context provided by caller
      * @param format the display format of phone number
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
      */
-    public static int setDisplayNumberFormat(Context context, int format, long subId) {
+    public static int setDisplayNumberFormat(int format, long subId) {
         if (VDBG) logd("[setDisplayNumberFormat]+ format:" + format + " subId:" + subId);
-        if (format < 0 || subId <= 0) {
+        if (format < 0 || !isValidSubId(subId)) {
             logd("[setDisplayNumberFormat]- fail, return -1");
             return -1;
         }
@@ -474,14 +493,13 @@
 
     /**
      * Set data roaming by simInfo index
-     * @param context Context provided by caller
      * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
      */
-    public static int setDataRoaming(Context context, int roaming, long subId) {
+    public static int setDataRoaming(int roaming, long subId) {
         if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
-        if (roaming < 0 || subId <= 0) {
+        if (roaming < 0 || !isValidSubId(subId)) {
             logd("[setDataRoaming]- fail");
             return -1;
         }
@@ -501,9 +519,11 @@
     }
 
     public static int getSlotId(long subId) {
-        if (VDBG) logd("[getSlotId]+ subId:" + subId);
+        if (!isValidSubId(subId)) {
+            logd("[getSlotId]- fail");
+        }
 
-        int result = 0;
+        int result = INVALID_SLOT_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -519,7 +539,10 @@
     }
 
     public static long[] getSubId(int slotId) {
-        if (VDBG) logd("[getSubId]+ slotId:" + slotId);
+        if (!isValidSlotId(slotId)) {
+            logd("[getSubId]- fail");
+            return null;
+        }
 
         long[] subId = null;
 
@@ -536,9 +559,12 @@
     }
 
     public static int getPhoneId(long subId) {
-        if (VDBG) logd("[getPhoneId]+ subId=" + subId);
+        if (!isValidSubId(subId)) {
+            logd("[getPhoneId]- fail");
+            return INVALID_PHONE_ID;
+        }
 
-        int result = 0;
+        int result = INVALID_PHONE_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -549,7 +575,7 @@
             // ignore it
         }
 
-        if (VDBG) logd("[getPhoneId]- phonId=" + result);
+        if (VDBG) logd("[getPhoneId]- phoneId=" + result);
         return result;
 
     }
@@ -583,23 +609,13 @@
         Rlog.d(LOG_TAG, "[SubManager] " + msg);
     }
 
-    public static long normalizeSubId(long subId) {
-        long retVal = (subId == DEFAULT_SUB_ID) ? getDefaultSubId() : subId;
-        Rlog.d(LOG_TAG, "[SubManager] normalizeSubId subId=" + retVal);
-        return retVal;
-    }
-
-    public static boolean validSubId(long subId) {
-        return (subId != DEFAULT_SUB_ID) && (subId != -1);
-    }
-
     /**
      * @return the "system" defaultSubId on a voice capable device this
      * will be getDefaultVoiceSubId() and on a data only device it will be
      * getDefaultDataSubId().
      */
     public static long getDefaultSubId() {
-        long subId = 1;
+        long subId = INVALID_SUB_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -615,7 +631,7 @@
     }
 
     public static long getDefaultVoiceSubId() {
-        long subId = 1;
+        long subId = INVALID_SUB_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -626,7 +642,7 @@
             // ignore it
         }
 
-        if (VDBG) logd("getDefaultSubId, sub id = " + subId);
+        if (VDBG) logd("getDefaultVoiceSubId, sub id = " + subId);
         return subId;
     }
 
@@ -638,32 +654,68 @@
                 iSub.setDefaultVoiceSubId(subId);
             }
         } catch (RemoteException ex) {
-         // ignore it
+            // ignore it
         }
     }
 
-    public static long getPreferredSmsSubId() {
-        // FIXME add framework support to get the preferred sub
-        return getDefaultSubId();
+    public static SubInfoRecord getDefaultVoiceSubInfo() {
+        return getSubInfoUsingSubId(getDefaultVoiceSubId());
     }
 
-    public static long getPreferredDataSubId() {
-        // FIXME add framework support to get the preferred sub
-        return getDefaultSubId();
+    public static int getDefaultVoicePhoneId() {
+        return getPhoneId(getDefaultVoiceSubId());
     }
 
-    public static long getDefaultDataSubId() {
+    public static long getDefaultSmsSubId() {
+        long subId = INVALID_SUB_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                return iSub.getDefaultDataSubId();
-            } else {
-                return -1;
+                subId = iSub.getDefaultSmsSubId();
             }
         } catch (RemoteException ex) {
-            return -1;
+            // ignore it
         }
+
+        if (VDBG) logd("getDefaultSmsSubId, sub id = " + subId);
+        return subId;
+    }
+
+    public static void setDefaultSmsSubId(long subId) {
+        if (VDBG) logd("setDefaultSmsSubId sub id = " + subId);
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                iSub.setDefaultSmsSubId(subId);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    public static SubInfoRecord getDefaultSmsSubInfo() {
+        return getSubInfoUsingSubId(getDefaultSmsSubId());
+    }
+
+    public static int getDefaultSmsPhoneId() {
+        return getPhoneId(getDefaultSmsSubId());
+    }
+
+    public static long getDefaultDataSubId() {
+        long subId = INVALID_SUB_ID;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                subId = iSub.getDefaultDataSubId();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        if (VDBG) logd("getDefaultDataSubId, sub id = " + subId);
+        return subId;
     }
 
     public static void setDefaultDataSubId(long subId) {
@@ -674,14 +726,19 @@
                 iSub.setDefaultDataSubId(subId);
             }
         } catch (RemoteException ex) {
-         // ignore it
+            // ignore it
         }
     }
 
-    public static void clearSubInfo()
-    {
-        if (VDBG) logd("[clearSubInfo]+");
+    public static SubInfoRecord getDefaultDataSubInfo() {
+        return getSubInfoUsingSubId(getDefaultDataSubId());
+    }
 
+    public static int getDefaultDataPhoneId() {
+        return getPhoneId(getDefaultDataSubId());
+    }
+
+    public static void clearSubInfo() {
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
@@ -694,10 +751,53 @@
         return;
     }
 
+    //FIXME this is vulnerable to race conditions
+    public static boolean allDefaultsSelected() {
+        if (getDefaultDataSubId() == INVALID_SUB_ID) {
+            return false;
+        }
+        if (getDefaultSmsSubId() == INVALID_SUB_ID) {
+            return false;
+        }
+        if (getDefaultVoiceSubId() == INVALID_SUB_ID) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * If a default is set to subscription which is not active, this will reset that default back to
+     * INVALID_SUB_ID.
+     */
+    public static void clearDefaultsForInactiveSubIds() {
+        if (VDBG) logd("clearDefaultsForInactiveSubIds");
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                iSub.clearDefaultsForInactiveSubIds();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    public static boolean isValidSubId(long subId) {
+        return subId > INVALID_SUB_ID ;
+    }
+
+    public static boolean isValidSlotId(int slotId) {
+        return slotId > INVALID_SLOT_ID && slotId < TelephonyManager.getDefault().getSimCount();
+    }
+
+    public static boolean isValidPhoneId(int phoneId) {
+        return phoneId > INVALID_PHONE_ID
+                && phoneId < TelephonyManager.getDefault().getPhoneCount();
+    }
+
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
-        long [] subId = SubscriptionManager.getSubId(phoneId);
-        if ((subId != null) && (subId.length >= 1)) {
-            putPhoneIdAndSubIdExtra(intent, phoneId, subId[0]);
+        long[] subIds = SubscriptionManager.getSubId(phoneId);
+        if (subIds != null && subIds.length > 0) {
+            putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
         } else {
             logd("putPhoneIdAndSubIdExtra: no valid subs");
         }
@@ -705,8 +805,35 @@
 
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, long subId) {
         if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
-        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); //FIXME: RENAME TO PHONE_ID_KEY ??
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+        intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
+        //FIXME this is using phoneId and slotId interchangeably
+        //Eventually, this should be removed as it is not the slot id
+        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+    }
+
+    /**
+     * @return the list of subId's that are active,
+     *         is never null but the length maybe 0.
+     */
+    public static long[] getActiveSubIdList() {
+        long[] subId = null;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                subId = iSub.getActiveSubIdList();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        if (subId == null) {
+            subId = new long[0];
+        }
+
+        return subId;
+
     }
 }
 
diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl
index 2aeb42f..63b7a53 100644
--- a/telephony/java/com/android/internal/telephony/IMms.aidl
+++ b/telephony/java/com/android/internal/telephony/IMms.aidl
@@ -30,7 +30,8 @@
      *
      * @param subId the SIM id
      * @param callingPkg the package name of the calling app
-     * @param pdu the MMS message encoded in standard MMS PDU format
+     * @param contentUri the content uri from which to read MMS message encoded in standard MMS
+     *  PDU format
      * @param locationUrl the optional location url for where this message should be sent to
      * @param configOverrides the carrier-specific messaging configuration values to override for
      *  sending the message. See {@link android.telephony.MessagingConfigurationManager} for the
@@ -38,8 +39,8 @@
      * @param sentIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is successfully sent, or failed
      */
-    void sendMessage(long subId, String callingPkg, in byte[] pdu, String locationUrl,
-            in ContentValues configOverrides, in PendingIntent sentIntent);
+    void sendMessage(long subId, String callingPkg, in Uri contentUri,
+            String locationUrl, in ContentValues configOverrides, in PendingIntent sentIntent);
 
     /**
      * Download an MMS message using known location and transaction id
@@ -48,6 +49,7 @@
      * @param callingPkg the package name of the calling app
      * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
      *  from the MMS WAP push notification
+     * @param contentUri a contentUri to which the downloaded MMS message will be written
      * @param configOverrides the carrier-specific messaging configuration values to override for
      *  downloading the message. See {@link android.telephony.MessagingConfigurationManager} for the
      *  value names and types.
@@ -55,7 +57,8 @@
      *  broadcast when the message is downloaded, or the download is failed
      */
     void downloadMessage(long subId, String callingPkg, String locationUrl,
-            in ContentValues configOverrides, in PendingIntent downloadedIntent);
+            in Uri contentUri, in ContentValues configOverrides,
+            in PendingIntent downloadedIntent);
 
     /**
      * Update the status of a pending (send-by-IP) MMS message handled by the carrier app.
@@ -104,14 +107,14 @@
       * Import a multimedia message into system's MMS store
       *
       * @param callingPkg the package name of the calling app
-      * @param pdu the PDU of the message to import
+      * @param contentUri the content uri from which to read PDU of the message to import
       * @param messageId the optional message id
       * @param timestampSecs the message timestamp in seconds
       * @param seen if the message is seen
       * @param read if the message is read
       * @return the message URI, null if failed
       */
-    Uri importMultimediaMessage(String callingPkg, in byte[] pdu, String messageId,
+    Uri importMultimediaMessage(String callingPkg, in Uri contentUri, String messageId,
             long timestampSecs, boolean seen, boolean read);
 
     /**
@@ -168,10 +171,10 @@
      * Add a multimedia message draft to system MMS store
      *
      * @param callingPkg the package name of the calling app
-     * @param pdu the PDU data of the draft MMS
+     * @param contentUri the content Uri from which to read PDU data of the draft MMS
      * @return the URI of the stored draft message
      */
-    Uri addMultimediaMessageDraft(String callingPkg, in byte[] pdu);
+    Uri addMultimediaMessageDraft(String callingPkg, in Uri contentUri);
 
     /**
      * Send a system stored MMS message
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6021ccf..e3b7d59 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -56,7 +56,7 @@
      * @param context Context provided by caller
      * @return Array list of currently inserted SubInfoRecord(s)
      */
-    List<SubInfoRecord> getActivatedSubInfoList();
+    List<SubInfoRecord> getActiveSubInfoList();
 
     /**
      * Get the SUB count of all SUB(s) in subinfo database
@@ -66,6 +66,13 @@
     int getAllSubInfoCount();
 
     /**
+     * Get the count of active SUB(s)
+     * @param context Context provided by caller
+     * @return active SIM count
+     */
+    int getActiveSubInfoCount();
+
+    /**
      * Add a new SubInfoRecord to subinfo database if needed
      * @param context Context provided by caller
      * @param iccId the IccId of the SIM card
@@ -109,7 +116,7 @@
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
      */
-    int setDispalyNumber(String number, long subId);
+    int setDisplayNumber(String number, long subId);
 
     /**
      * Set number display format. 0: none, 1: the first four digits, 2: the last four digits
@@ -150,4 +157,12 @@
     long getDefaultVoiceSubId();
 
     void setDefaultVoiceSubId(long subId);
+
+    long getDefaultSmsSubId();
+
+    void setDefaultSmsSubId(long subId);
+
+    void clearDefaultsForInactiveSubIds();
+
+    long[] getActiveSubIdList();
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index b4b1ea5..62b5596 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -136,14 +136,6 @@
     /** APN type for IA Emergency PDN */
     public static final String APN_TYPE_EMERGENCY = "emergency";
 
-    // FIXME: This looks to be used as default phoneId, rename
-    // or use SubscriptionManager.DEFAULT_SUB_ID
-    public static final int DEFAULT_SUBSCRIPTION = 0;
-
-    // FIXME: This looks to be used as invalid phoneId, rename
-    // or use SubscriptionManager.INVALID_SUB_ID
-    public static final int INVALID_SUBSCRIPTION = -1;
-
     public static final int RIL_CARD_MAX_APPS    = 8;
 
     public static final int DEFAULT_CARD_INDEX   = 0;
@@ -154,10 +146,14 @@
 
     public static final int MAX_PHONE_COUNT_TRI_SIM = 3;
 
-    public static final String SUBSCRIPTION_KEY  = "subscription";
+    public static final String PHONE_KEY = "phone";
 
     public static final String SLOT_KEY  = "slot";
 
+    // FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
+    // FIXME: extensive, and see if this should be an array of all active subId's or ...?
+    public static final String SUBSCRIPTION_KEY  = "subscription";
+
     public static final String SUB_SETTING  = "subSettings";
 
     public static final int SUB1 = 0;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 85ceefd..e7aca90 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -391,4 +391,14 @@
      */
     public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED
             = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
+
+    /**
+     * Broadcast Action: The default sms subscription has changed.  This has the following
+     * extra values:</p>
+     * <ul>
+     *   <li><em>subscription</em> - A int, the current sms default subscription.</li>
+     * </ul>
+     */
+    public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
+            = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
 }