Merge "Make keysetmgrservice gurantees explicit." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index f180460..5126123 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4019,10 +4019,12 @@
     ctor public AssistContent();
     method public android.content.ClipData getClipData();
     method public android.os.Bundle getExtras();
+    method public java.lang.String getStructuredData();
     method public android.net.Uri getWebUri();
     method public boolean isAppProvidedIntent();
     method public void setClipData(android.content.ClipData);
     method public void setIntent(android.content.Intent);
+    method public void setStructuredData(java.lang.String);
     method public void setWebUri(android.net.Uri);
   }
 
@@ -13325,6 +13327,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> SENSOR_INFO_MAX_FRAME_DURATION;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.SizeF> SENSOR_INFO_PHYSICAL_SIZE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<android.graphics.Rect> SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> SENSOR_INFO_SENSITIVITY_RANGE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_INFO_TIMESTAMP_SOURCE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_INFO_WHITE_LEVEL;
@@ -23419,6 +23422,7 @@
 
   public final class PowerManager {
     method public boolean isDeviceIdleMode();
+    method public boolean isIgnoringBatteryOptimizations(java.lang.String);
     method public boolean isInteractive();
     method public boolean isPowerSaveMode();
     method public deprecated boolean isScreenOn();
@@ -23672,6 +23676,7 @@
     field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
     field public static final java.lang.String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
     field public static final java.lang.String DISALLOW_FACTORY_RESET = "no_factory_reset";
+    field public static final java.lang.String DISALLOW_FUN = "no_fun";
     field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
     field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
     field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
@@ -28319,30 +28324,6 @@
 
 package android.security {
 
-  public class EcIesParameterSpec implements java.security.spec.AlgorithmParameterSpec {
-    method public int getDemCipherKeySize();
-    method public java.lang.String getDemCipherTransformation();
-    method public java.lang.String getDemMacAlgorithm();
-    method public int getDemMacKeySize();
-    method public java.lang.String getKemKdfAlgorithm();
-    method public int getKemPointFormat();
-    field public static final android.security.EcIesParameterSpec DEFAULT;
-    field public static final int POINT_FORMAT_COMPRESSED = 1; // 0x1
-    field public static final int POINT_FORMAT_UNCOMPRESSED = 0; // 0x0
-    field public static final int POINT_FORMAT_UNSPECIFIED = -1; // 0xffffffff
-  }
-
-  public static class EcIesParameterSpec.Builder {
-    ctor public EcIesParameterSpec.Builder();
-    method public android.security.EcIesParameterSpec build();
-    method public android.security.EcIesParameterSpec.Builder setDemCipherKeySize(int);
-    method public android.security.EcIesParameterSpec.Builder setDemCipherTransformation(java.lang.String);
-    method public android.security.EcIesParameterSpec.Builder setDemMacAlgorithm(java.lang.String);
-    method public android.security.EcIesParameterSpec.Builder setDemMacKeySize(int);
-    method public android.security.EcIesParameterSpec.Builder setKemKdfAlgorithm(java.lang.String);
-    method public android.security.EcIesParameterSpec.Builder setKemPointFormat(int);
-  }
-
   public final class KeyChain {
     ctor public KeyChain();
     method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -30560,6 +30541,7 @@
     field public static final java.lang.String ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER";
     field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
     field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
+    field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED";
     field public static final java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
     field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
     field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
@@ -30637,9 +30619,11 @@
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
+    field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+    field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
-    field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "key_enable_dialer_vibration_bool";
+    field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_vibration_bool";
     field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
     field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
     field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
diff --git a/api/system-current.txt b/api/system-current.txt
index 025fbde..d3823fc 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4114,10 +4114,12 @@
     ctor public AssistContent();
     method public android.content.ClipData getClipData();
     method public android.os.Bundle getExtras();
+    method public java.lang.String getStructuredData();
     method public android.net.Uri getWebUri();
     method public boolean isAppProvidedIntent();
     method public void setClipData(android.content.ClipData);
     method public void setIntent(android.content.Intent);
+    method public void setStructuredData(java.lang.String);
     method public void setWebUri(android.net.Uri);
   }
 
@@ -13645,6 +13647,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> SENSOR_INFO_MAX_FRAME_DURATION;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.SizeF> SENSOR_INFO_PHYSICAL_SIZE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<android.graphics.Rect> SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> SENSOR_INFO_SENSITIVITY_RANGE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_INFO_TIMESTAMP_SOURCE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SENSOR_INFO_WHITE_LEVEL;
@@ -25341,6 +25344,7 @@
 
   public final class PowerManager {
     method public boolean isDeviceIdleMode();
+    method public boolean isIgnoringBatteryOptimizations(java.lang.String);
     method public boolean isInteractive();
     method public boolean isPowerSaveMode();
     method public boolean isScreenBrightnessBoosted();
@@ -25606,6 +25610,7 @@
     field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
     field public static final java.lang.String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
     field public static final java.lang.String DISALLOW_FACTORY_RESET = "no_factory_reset";
+    field public static final java.lang.String DISALLOW_FUN = "no_fun";
     field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
     field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
     field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
@@ -30356,30 +30361,6 @@
 
 package android.security {
 
-  public class EcIesParameterSpec implements java.security.spec.AlgorithmParameterSpec {
-    method public int getDemCipherKeySize();
-    method public java.lang.String getDemCipherTransformation();
-    method public java.lang.String getDemMacAlgorithm();
-    method public int getDemMacKeySize();
-    method public java.lang.String getKemKdfAlgorithm();
-    method public int getKemPointFormat();
-    field public static final android.security.EcIesParameterSpec DEFAULT;
-    field public static final int POINT_FORMAT_COMPRESSED = 1; // 0x1
-    field public static final int POINT_FORMAT_UNCOMPRESSED = 0; // 0x0
-    field public static final int POINT_FORMAT_UNSPECIFIED = -1; // 0xffffffff
-  }
-
-  public static class EcIesParameterSpec.Builder {
-    ctor public EcIesParameterSpec.Builder();
-    method public android.security.EcIesParameterSpec build();
-    method public android.security.EcIesParameterSpec.Builder setDemCipherKeySize(int);
-    method public android.security.EcIesParameterSpec.Builder setDemCipherTransformation(java.lang.String);
-    method public android.security.EcIesParameterSpec.Builder setDemMacAlgorithm(java.lang.String);
-    method public android.security.EcIesParameterSpec.Builder setDemMacKeySize(int);
-    method public android.security.EcIesParameterSpec.Builder setKemKdfAlgorithm(java.lang.String);
-    method public android.security.EcIesParameterSpec.Builder setKemPointFormat(int);
-  }
-
   public final class KeyChain {
     ctor public KeyChain();
     method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -32776,6 +32757,7 @@
     field public static final java.lang.String ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER";
     field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
     field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
+    field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED";
     field public static final java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
     field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
     field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
@@ -32857,9 +32839,11 @@
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
+    field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+    field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
-    field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "key_enable_dialer_vibration_bool";
+    field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_vibration_bool";
     field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
     field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
     field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index c5af992..449a4ab 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -90,9 +90,6 @@
 
     virtual void onZygoteInit()
     {
-        // Re-enable tracing now that we're no longer in Zygote.
-        atrace_set_tracing_enabled(true);
-
         sp<ProcessState> proc = ProcessState::self();
         ALOGV("App process: starting thread pool.\n");
         proc->startThreadPool();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e21c04a..828dc0a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5375,6 +5375,7 @@
     }
 
     public static void main(String[] args) {
+        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
         SamplingProfilerIntegration.start();
 
         // CloseGuard defaults to true and can be quite spammy.  We
@@ -5409,6 +5410,8 @@
                     LogPrinter(Log.DEBUG, "ActivityThread"));
         }
 
+        // End of event ActivityThreadMain.
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         Looper.loop();
 
         throw new RuntimeException("Main thread loop unexpectedly exited");
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
index 0df9ce5..ad2ba39 100644
--- a/core/java/android/app/AssistContent.java
+++ b/core/java/android/app/AssistContent.java
@@ -33,6 +33,7 @@
 public class AssistContent {
     private boolean mIsAppProvidedIntent = false;
     private Intent mIntent;
+    private String mStructuredData;
     private ClipData mClipData;
     private Uri mUri;
     private final Bundle mExtras;
@@ -125,6 +126,22 @@
     }
 
     /**
+     * Sets optional structured data regarding the content being viewed. The provided data
+     * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the
+     * <a href="http://schema.org/">schema.org</a> vocabulary.
+     */
+    public void setStructuredData(String structuredData) {
+        mStructuredData = structuredData;
+    }
+
+    /**
+     * Returns the current {@link #setStructuredData}.
+     */
+    public String getStructuredData() {
+        return mStructuredData;
+    }
+
+    /**
      * Set a web URI associated with the current data being shown to the user.
      * This URI could be opened in a web browser, or in the app as an
      * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently
@@ -163,6 +180,9 @@
         if (in.readInt() != 0) {
             mUri = Uri.CREATOR.createFromParcel(in);
         }
+        if (in.readInt() != 0) {
+            mStructuredData = in.readString();
+        }
         mIsAppProvidedIntent = in.readInt() == 1;
         mExtras = in.readBundle();
     }
@@ -187,6 +207,12 @@
         } else {
             dest.writeInt(0);
         }
+        if (mStructuredData != null) {
+            dest.writeInt(1);
+            dest.writeString(mStructuredData);
+        } else {
+            dest.writeInt(0);
+        }
         dest.writeInt(mIsAppProvidedIntent ? 1 : 0);
         dest.writeBundle(mExtras);
     }
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 02e26a5..903411e 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -28,7 +28,6 @@
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.LogWriter;
-import android.util.Pair;
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
@@ -1005,13 +1004,20 @@
                 outFragment.getExitTransition());
     }
 
-    private static Transition getSharedElementTransition(Fragment inFragment, Fragment outFragment,
-            boolean isBack) {
+    private static TransitionSet getSharedElementTransition(Fragment inFragment,
+            Fragment outFragment, boolean isBack) {
         if (inFragment == null || outFragment == null) {
             return null;
         }
-        return cloneTransition(isBack ? outFragment.getSharedElementReturnTransition() :
-                inFragment.getSharedElementEnterTransition());
+        Transition transition = cloneTransition(isBack
+                ? outFragment.getSharedElementReturnTransition()
+                : inFragment.getSharedElementEnterTransition());
+        if (transition == null) {
+            return null;
+        }
+        TransitionSet transitionSet = new TransitionSet();
+        transitionSet.addTransition(transition);
+        return transitionSet;
     }
 
     private static ArrayList<View> captureExitingViews(Transition exitTransition,
@@ -1070,7 +1076,7 @@
      * capturing the final state of the Transition.</p>
      */
     private ArrayList<View> addTransitionTargets(final TransitionState state,
-            final Transition enterTransition, final Transition sharedElementTransition,
+            final Transition enterTransition, final TransitionSet sharedElementTransition,
             final Transition overallTransition, final View container,
             final Fragment inFragment, final Fragment outFragment,
             final ArrayList<View> hiddenFragmentViews, final boolean isBack,
@@ -1094,11 +1100,8 @@
                         if (sharedElementTransition != null) {
                             namedViews = mapSharedElementsIn(state, isBack, inFragment);
                             removeTargets(sharedElementTransition, sharedElementTargets);
-                            sharedElementTargets.clear();
-                            sharedElementTargets.add(state.nonExistentView);
-                            sharedElementTargets.addAll(namedViews.values());
-
-                            addTargets(sharedElementTransition, sharedElementTargets);
+                            setSharedElementTargets(sharedElementTransition,
+                                    state.nonExistentView, namedViews, sharedElementTargets);
 
                             setEpicenterIn(namedViews, state);
 
@@ -1241,8 +1244,8 @@
             Fragment outFragment = firstOutFragments.get(containerId);
 
             Transition enterTransition = getEnterTransition(inFragment, isBack);
-            Transition sharedElementTransition = getSharedElementTransition(inFragment, outFragment,
-                    isBack);
+            TransitionSet sharedElementTransition =
+                    getSharedElementTransition(inFragment, outFragment, isBack);
             Transition exitTransition = getExitTransition(outFragment, isBack);
 
             if (enterTransition == null && sharedElementTransition == null &&
@@ -1256,9 +1259,8 @@
             ArrayList<View> sharedElementTargets = new ArrayList<View>();
             if (sharedElementTransition != null) {
                 namedViews = remapSharedElements(state, outFragment, isBack);
-                sharedElementTargets.add(state.nonExistentView);
-                sharedElementTargets.addAll(namedViews.values());
-                addTargets(sharedElementTransition, sharedElementTargets);
+                setSharedElementTargets(sharedElementTransition,
+                        state.nonExistentView, namedViews, sharedElementTargets);
 
                 // Notify the start of the transition.
                 SharedElementCallback callback = isBack ?
@@ -1294,8 +1296,8 @@
             if (transition != null) {
                 ArrayList<View> hiddenFragments = new ArrayList<View>();
                 ArrayList<View> enteringViews = addTransitionTargets(state, enterTransition,
-                        sharedElementTransition, transition, sceneRoot, inFragment, outFragment,
-                        hiddenFragments, isBack, sharedElementTargets);
+                        sharedElementTransition, transition, sceneRoot, inFragment,
+                        outFragment, hiddenFragments, isBack, sharedElementTargets);
 
                 transition.setNameOverrides(state.nameOverrides);
                 // We want to exclude hidden views later, so we need a non-null list in the
@@ -1307,12 +1309,74 @@
                 // Remove the view targeting after the transition starts
                 removeTargetedViewsFromTransitions(sceneRoot, state.nonExistentView,
                         enterTransition, enteringViews, exitTransition, exitingViews,
-                        sharedElementTransition, sharedElementTargets, transition, hiddenFragments);
+                        sharedElementTransition, sharedElementTargets, transition,
+                        hiddenFragments);
             }
         }
     }
 
     /**
+     * Finds all children of the shared elements and sets the wrapping TransitionSet
+     * targets to point to those. It also limits transitions that have no targets to the
+     * specific shared elements. This allows developers to target child views of the
+     * shared elements specifically, but this doesn't happen by default.
+     */
+    private static void setSharedElementTargets(TransitionSet transition,
+            View nonExistentView, ArrayMap<String, View> namedViews,
+            ArrayList<View> sharedElementTargets) {
+        sharedElementTargets.clear();
+        sharedElementTargets.addAll(namedViews.values());
+
+        final List<View> views = transition.getTargets();
+        views.clear();
+        final int count = sharedElementTargets.size();
+        for (int i = 0; i < count; i++) {
+            final View view = sharedElementTargets.get(i);
+            bfsAddViewChildren(views, view);
+        }
+        sharedElementTargets.add(nonExistentView);
+        addTargets(transition, sharedElementTargets);
+    }
+
+    /**
+     * Uses a breadth-first scheme to add startView and all of its children to views.
+     * It won't add a child if it is already in views.
+     */
+    private static void bfsAddViewChildren(final List<View> views, final View startView) {
+        final int startIndex = views.size();
+        if (containedBeforeIndex(views, startView, startIndex)) {
+            return; // This child is already in the list, so all its children are also.
+        }
+        views.add(startView);
+        for (int index = startIndex; index < views.size(); index++) {
+            final View view = views.get(index);
+            if (view instanceof ViewGroup) {
+                ViewGroup viewGroup = (ViewGroup) view;
+                final int childCount =  viewGroup.getChildCount();
+                for (int childIndex = 0; childIndex < childCount; childIndex++) {
+                    final View child = viewGroup.getChildAt(childIndex);
+                    if (!containedBeforeIndex(views, child, startIndex)) {
+                        views.add(child);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Does a linear search through views for view, limited to maxIndex.
+     */
+    private static boolean containedBeforeIndex(final List<View> views, final View view,
+            final int maxIndex) {
+        for (int i = 0; i < maxIndex; i++) {
+            if (views.get(i) == view) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * After the transition has started, remove all targets that we added to the transitions
      * so that the transitions are left in a clean state.
      */
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9f49154..ed20086 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -403,8 +403,9 @@
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
-     * location specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
+     * A String extra holding the URL-safe base64 encoded SHA-256 or SHA-1 hash (see notes below) of
+     * the file at download location specified in
+     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
      *
      * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM} should be
      * present. The provided checksum should match the checksum of the file at the download
@@ -413,12 +414,17 @@
      *
      * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
      * provisioning via an NFC bump.
+     *
+     * <p><strong>Note:</strong> for devices running {@link android.os.Build.VERSION_CODES#LOLLIPOP}
+     * and {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} only SHA-1 hash is supported.
+     * Starting from {@link android.os.Build.VERSION_CODES#MNC}, this parameter accepts SHA-256 in
+     * addition to SHA-1. Support for SHA-1 is likely to be removed in future OS releases.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
+     * A String extra holding the URL-safe base64 encoded SHA-256 checksum of any signature of the
      * android package archive at the download location specified in {@link
      * #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
      *
@@ -510,7 +516,7 @@
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
+     * A String extra holding the URL-safe base64 encoded SHA-256 checksum of the file at download
      * location specified in
      * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
@@ -526,7 +532,7 @@
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
+     * A String extra holding the URL-safe base64 encoded SHA-256 checksum of any signature of the
      * android package archive at the download location specified in {@link
      * #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
@@ -924,7 +930,7 @@
 
     /**
      * Constant for {@link #setPasswordQuality}: the policy requires some kind
-     * of password, but doesn't care what it is.  Note that quality constants
+     * of password or pattern, but doesn't care what it is. Note that quality constants
      * are ordered so that higher values are more restrictive.
      */
     public static final int PASSWORD_QUALITY_SOMETHING = 0x10000;
diff --git a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
index 161c339..834a587 100644
--- a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
+++ b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
@@ -28,10 +28,10 @@
 public final class BluetoothActivityEnergyInfo implements Parcelable {
     private final long mTimestamp;
     private final int mBluetoothStackState;
-    private final int mControllerTxTimeMs;
-    private final int mControllerRxTimeMs;
-    private final int mControllerIdleTimeMs;
-    private final int mControllerEnergyUsed;
+    private final long mControllerTxTimeMs;
+    private final long mControllerRxTimeMs;
+    private final long mControllerIdleTimeMs;
+    private final long mControllerEnergyUsed;
 
     public static final int BT_STACK_STATE_INVALID = 0;
     public static final int BT_STACK_STATE_STATE_ACTIVE = 1;
@@ -39,7 +39,7 @@
     public static final int BT_STACK_STATE_STATE_IDLE = 3;
 
     public BluetoothActivityEnergyInfo(long timestamp, int stackState,
-                                       int txTime, int rxTime, int idleTime, int energyUsed) {
+                                       long txTime, long rxTime, long idleTime, long energyUsed) {
         mTimestamp = timestamp;
         mBluetoothStackState = stackState;
         mControllerTxTimeMs = txTime;
@@ -65,10 +65,10 @@
         public BluetoothActivityEnergyInfo createFromParcel(Parcel in) {
             long timestamp = in.readLong();
             int stackState = in.readInt();
-            int txTime = in.readInt();
-            int rxTime = in.readInt();
-            int idleTime = in.readInt();
-            int energyUsed = in.readInt();
+            long txTime = in.readLong();
+            long rxTime = in.readLong();
+            long idleTime = in.readLong();
+            long energyUsed = in.readLong();
             return new BluetoothActivityEnergyInfo(timestamp, stackState,
                     txTime, rxTime, idleTime, energyUsed);
         }
@@ -80,10 +80,10 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(mTimestamp);
         out.writeInt(mBluetoothStackState);
-        out.writeInt(mControllerTxTimeMs);
-        out.writeInt(mControllerRxTimeMs);
-        out.writeInt(mControllerIdleTimeMs);
-        out.writeInt(mControllerEnergyUsed);
+        out.writeLong(mControllerTxTimeMs);
+        out.writeLong(mControllerRxTimeMs);
+        out.writeLong(mControllerIdleTimeMs);
+        out.writeLong(mControllerEnergyUsed);
     }
 
     public int describeContents() {
@@ -100,21 +100,21 @@
     /**
      * @return tx time in ms
      */
-    public int getControllerTxTimeMillis() {
+    public long getControllerTxTimeMillis() {
         return mControllerTxTimeMs;
     }
 
     /**
      * @return rx time in ms
      */
-    public int getControllerRxTimeMillis() {
+    public long getControllerRxTimeMillis() {
         return mControllerRxTimeMs;
     }
 
     /**
      * @return idle time in ms
      */
-    public int getControllerIdleTimeMillis() {
+    public long getControllerIdleTimeMillis() {
         return mControllerIdleTimeMs;
     }
 
@@ -122,7 +122,7 @@
      * product of current(mA), voltage(V) and time(ms)
      * @return energy used
      */
-    public int getControllerEnergyUsed() {
+    public long getControllerEnergyUsed() {
         return mControllerEnergyUsed;
     }
 
@@ -137,8 +137,8 @@
      * @return if the record is valid
      */
     public boolean isValid() {
-        return ((getControllerTxTimeMillis() !=0) ||
-                (getControllerRxTimeMillis() !=0) ||
-                (getControllerIdleTimeMillis() !=0));
+        return ((mControllerTxTimeMs !=0) ||
+                (mControllerRxTimeMs !=0) ||
+                (mControllerIdleTimeMs !=0));
     }
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 970623a..83ce087 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2248,6 +2248,7 @@
             //@hide: VOICE_INTERACTION_MANAGER_SERVICE,
             //@hide: BACKUP_SERVICE,
             DROPBOX_SERVICE,
+            //@hide: DEVICE_IDLE_CONTROLLER,
             DEVICE_POLICY_SERVICE,
             UI_MODE_SERVICE,
             DOWNLOAD_SERVICE,
@@ -2874,6 +2875,13 @@
     public static final String DROPBOX_SERVICE = "dropbox";
 
     /**
+     * System service name for the DeviceIdleController.  There is no Java API for this.
+     * @see #getSystemService
+     * @hide
+     */
+    public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
+
+    /**
      * Use with {@link #getSystemService} to retrieve a
      * {@link android.app.admin.DevicePolicyManager} for working with global
      * device policy management.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index b69ca88..27d14b3 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1093,14 +1093,28 @@
      * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world
      * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
      * (depth) in pixel coordinates.</p>
+     * <p>Note that the coordinate system for this transform is the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} system,
+     * where <code>(0,0)</code> is the top-left of the
+     * preCorrectionActiveArraySize rectangle. Once the pose and
+     * intrinsic calibration transforms have been applied to a
+     * world point, then the android.lens.radialDistortion
+     * transform needs to be applied, and the result adjusted to
+     * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
+     * system (where <code>(0, 0)</code> is the top-left of the
+     * activeArraySize rectangle), to determine the final pixel
+     * coordinate of the world point for processed (non-RAW)
+     * output buffers.</p>
      * <p><b>Units</b>:
-     * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
-     * system.</p>
+     * Pixels in the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * coordinate system.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
@@ -1109,13 +1123,13 @@
     /**
      * <p>The correction coefficients to correct for this camera device's
      * radial and tangential lens distortion.</p>
-     * <p>Three radial distortion coefficients <code>[kappa_1, kappa_2,
+     * <p>Four radial distortion coefficients <code>[kappa_0, kappa_1, kappa_2,
      * kappa_3]</code> and two tangential distortion coefficients
      * <code>[kappa_4, kappa_5]</code> that can be used to correct the
      * lens's geometric distortion with the mapping equations:</p>
-     * <pre><code> x_c = x_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
+     * <pre><code> x_c = x_i * ( kappa_0 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
      *        kappa_4 * (2 * x_i * y_i) + kappa_5 * ( r^2 + 2 * x_i^2 )
-     *  y_c = y_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
+     *  y_c = y_i * ( kappa_0 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
      *        kappa_5 * (2 * x_i * y_i) + kappa_4 * ( r^2 + 2 * y_i^2 )
      * </code></pre>
      * <p>Here, <code>[x_c, y_c]</code> are the coordinates to sample in the
@@ -1959,22 +1973,25 @@
             new Key<Integer>("android.scaler.croppingType", int.class);
 
     /**
-     * <p>The area of the image sensor which corresponds to
-     * active pixels.</p>
-     * <p>This is the region of the sensor that actually receives light from the scene.
-     * Therefore, the size of this region determines the maximum field of view and the maximum
-     * number of pixels that an image from this sensor can contain.</p>
-     * <p>The rectangle is defined in terms of the full pixel array; (0,0) is the top-left of the
-     * full pixel array, and the size of the full pixel array is given by
+     * <p>The area of the image sensor which corresponds to active pixels after any geometric
+     * distortion correction has been applied.</p>
+     * <p>This is the rectangle representing the size of the active region of the sensor (i.e.
+     * the region that actually receives light from the scene) after any geometric correction
+     * has been applied, and should be treated as the maximum size in pixels of any of the
+     * image output formats aside from the raw formats.</p>
+     * <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of
+     * the full pixel array, and the size of the full pixel array is given by
      * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</p>
-     * <p>Most other keys listing pixel coordinates have their coordinate systems based on the
-     * active array, with <code>(0, 0)</code> being the top-left of the active array rectangle.</p>
+     * <p>The coordinate system for most other keys that list pixel coordinates, including
+     * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, is defined relative to the active array rectangle given in
+     * this field, with <code>(0, 0)</code> being the top-left of this rectangle.</p>
      * <p>The active array may be smaller than the full pixel array, since the full array may
-     * include black calibration pixels or other inactive regions.</p>
+     * include black calibration pixels or other inactive regions, and geometric correction
+     * resulting in scaling or cropping may have been applied.</p>
      * <p><b>Units</b>: Pixel coordinates on the image sensor</p>
-     * <p><b>Range of valid values:</b><br></p>
      * <p>This key is available on all devices.</p>
      *
+     * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
      */
     @PublicKey
@@ -1982,6 +1999,70 @@
             new Key<android.graphics.Rect>("android.sensor.info.activeArraySize", android.graphics.Rect.class);
 
     /**
+     * <p>The area of the image sensor which corresponds to active pixels prior to the
+     * application of any geometric distortion correction.</p>
+     * <p>This is the rectangle representing the size of the active region of the sensor (i.e.
+     * the region that actually receives light from the scene) before any geometric correction
+     * has been applied, and should be treated as the active region rectangle for any of the
+     * raw formats.  All metadata associated with raw processing (e.g. the lens shading
+     * correction map, and radial distortion fields) treats the top, left of this rectangle as
+     * the origin, (0,0).</p>
+     * <p>The size of this region determines the maximum field of view and the maximum number of
+     * pixels that an image from this sensor can contain, prior to the application of
+     * geometric distortion correction. The effective maximum pixel dimensions of a
+     * post-distortion-corrected image is given by the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}
+     * field, and the effective maximum field of view for a post-distortion-corrected image
+     * can be calculated by applying the geometric distortion correction fields to this
+     * rectangle, and cropping to the rectangle given in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+     * <p>E.g. to calculate position of a pixel, (x,y), in a processed YUV output image with the
+     * dimensions in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} given the position of a pixel,
+     * (x', y'), in the raw pixel array with dimensions give in
+     * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}:</p>
+     * <ol>
+     * <li>Choose a pixel (x', y') within the active array region of the raw buffer given in
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, otherwise this pixel is considered
+     * to be outside of the FOV, and will not be shown in the processed output image.</li>
+     * <li>Apply geometric distortion correction to get the post-distortion pixel coordinate,
+     * (x_i, y_i). When applying geometric correction metadata, note that metadata for raw
+     * buffers is defined relative to the top, left of the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} rectangle.</li>
+     * <li>If the resulting corrected pixel coordinate is within the region given in
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, then the position of this pixel in the
+     * processed output image buffer is <code>(x_i - activeArray.left, y_i - activeArray.top)</code>,
+     * when the top, left coordinate of that buffer is treated as (0, 0).</li>
+     * </ol>
+     * <p>Thus, for pixel x',y' = (25, 25) on a sensor where {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}
+     * is (100,100), {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} is (10, 10, 100, 100),
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is (20, 20, 80, 80), and the geometric distortion
+     * correction doesn't change the pixel coordinate, the resulting pixel selected in
+     * pixel coordinates would be x,y = (25, 25) relative to the top,left of the raw buffer
+     * with dimensions given in {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}, and would be (5, 5)
+     * relative to the top,left of post-processed YUV output buffer with dimensions given in
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+     * <p>The currently supported fields that correct for geometric distortion are:</p>
+     * <ol>
+     * <li>android.lens.radialDistortion.</li>
+     * </ol>
+     * <p>If all of the geometric distortion fields are no-ops, this rectangle will be the same
+     * as the post-distortion-corrected rectangle given in
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+     * <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of
+     * the full pixel array, and the size of the full pixel array is given by
+     * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</p>
+     * <p>The pre-correction active array may be smaller than the full pixel array, since the
+     * full array may include black calibration pixels or other inactive regions.</p>
+     * <p><b>Units</b>: Pixel coordinates on the image sensor</p>
+     * <p>This key is available on all devices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
+     */
+    @PublicKey
+    public static final Key<android.graphics.Rect> SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE =
+            new Key<android.graphics.Rect>("android.sensor.info.preCorrectionActiveArraySize", android.graphics.Rect.class);
+
+    /**
      * <p>Range of sensitivities for {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} supported by this
      * camera device.</p>
      * <p>The values are the standard ISO sensitivity values,
@@ -2089,22 +2170,24 @@
     /**
      * <p>Dimensions of the full pixel array, possibly
      * including black calibration pixels.</p>
-     * <p>The pixel count of the full pixel array,
-     * which covers {@link CameraCharacteristics#SENSOR_INFO_PHYSICAL_SIZE android.sensor.info.physicalSize} area.</p>
-     * <p>If a camera device supports raw sensor formats, either this
-     * or {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is the maximum output
-     * raw size listed in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}.
-     * If a size corresponding to pixelArraySize is listed, the resulting
-     * raw sensor image will include black pixels.</p>
+     * <p>The pixel count of the full pixel array of the image sensor, which covers
+     * {@link CameraCharacteristics#SENSOR_INFO_PHYSICAL_SIZE android.sensor.info.physicalSize} area.  This represents the full pixel dimensions of
+     * the raw buffers produced by this sensor.</p>
+     * <p>If a camera device supports raw sensor formats, either this or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} is the maximum dimensions for the raw
+     * output formats listed in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} (this depends on
+     * whether or not the image sensor returns buffers containing pixels that are not
+     * part of the active array region for blacklevel calibration or other purposes).</p>
      * <p>Some parts of the full pixel array may not receive light from the scene,
-     * or are otherwise inactive.  The {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} key
-     * defines the rectangle of active pixels that actually forms an image.</p>
+     * or be otherwise inactive.  The {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} key
+     * defines the rectangle of active pixels that will be included in processed image
+     * formats.</p>
      * <p><b>Units</b>: Pixels</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
-     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PHYSICAL_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.util.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE =
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 3bb2fdb..da216aa 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2655,14 +2655,28 @@
      * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world
      * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
      * (depth) in pixel coordinates.</p>
+     * <p>Note that the coordinate system for this transform is the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} system,
+     * where <code>(0,0)</code> is the top-left of the
+     * preCorrectionActiveArraySize rectangle. Once the pose and
+     * intrinsic calibration transforms have been applied to a
+     * world point, then the android.lens.radialDistortion
+     * transform needs to be applied, and the result adjusted to
+     * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
+     * system (where <code>(0, 0)</code> is the top-left of the
+     * activeArraySize rectangle), to determine the final pixel
+     * coordinate of the world point for processed (non-RAW)
+     * output buffers.</p>
      * <p><b>Units</b>:
-     * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
-     * system.</p>
+     * Pixels in the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * coordinate system.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
@@ -2671,13 +2685,13 @@
     /**
      * <p>The correction coefficients to correct for this camera device's
      * radial and tangential lens distortion.</p>
-     * <p>Three radial distortion coefficients <code>[kappa_1, kappa_2,
+     * <p>Four radial distortion coefficients <code>[kappa_0, kappa_1, kappa_2,
      * kappa_3]</code> and two tangential distortion coefficients
      * <code>[kappa_4, kappa_5]</code> that can be used to correct the
      * lens's geometric distortion with the mapping equations:</p>
-     * <pre><code> x_c = x_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
+     * <pre><code> x_c = x_i * ( kappa_0 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
      *        kappa_4 * (2 * x_i * y_i) + kappa_5 * ( r^2 + 2 * x_i^2 )
-     *  y_c = y_i * ( 1 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
+     *  y_c = y_i * ( kappa_0 + kappa_1 * r^2 + kappa_2 * r^4 + kappa_3 * r^6 ) +
      *        kappa_5 * (2 * x_i * y_i) + kappa_4 * ( r^2 + 2 * y_i^2 )
      * </code></pre>
      * <p>Here, <code>[x_c, y_c]</code> are the coordinates to sample in the
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 8512b23..a1ebe6a 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -2053,8 +2053,10 @@
                 requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
 
         // Overwrite the capture intent to make sure a good value is set.
-        Surface[] surfaces = (Surface[])outputSurfaces.toArray();
-        if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(surfaces[0])) {
+        Iterator<Surface> iterator = outputSurfaces.iterator();
+        Surface firstSurface = iterator.next();
+        Surface secondSurface = null;
+        if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(firstSurface)) {
             singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
                     CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
         } else {
@@ -2071,19 +2073,20 @@
                     requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
             doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
                     CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
-            doubleTargetRequestBuilder.addTarget(surfaces[0]);
-            doubleTargetRequestBuilder.addTarget(surfaces[1]);
+            doubleTargetRequestBuilder.addTarget(firstSurface);
+            secondSurface = iterator.next();
+            doubleTargetRequestBuilder.addTarget(secondSurface);
             doubleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
             // Make sure singleTargetRequestBuilder contains only recording surface for
             // preview + recording case.
-            Surface recordingSurface = surfaces[0];
+            Surface recordingSurface = firstSurface;
             if (!SurfaceUtils.isSurfaceForHwVideoEncoder(recordingSurface)) {
-                recordingSurface = surfaces[1];
+                recordingSurface = secondSurface;
             }
             singleTargetRequestBuilder.addTarget(recordingSurface);
         } else {
             // Single output case: either recording or preview.
-            singleTargetRequestBuilder.addTarget(surfaces[0]);
+            singleTargetRequestBuilder.addTarget(firstSurface);
         }
 
         // Generate the final request list.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3a3c47d..a2ca41c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -801,28 +801,6 @@
     }
 
     /**
-     * Returns details about the Provisioning or currently active default data network. When
-     * connected, this network is the default route for outgoing connections.
-     * You should always check {@link NetworkInfo#isConnected()} before initiating
-     * network traffic. This may return {@code null} when there is no default
-     * network.
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
-     *
-     * @return a {@link NetworkInfo} object for the current default network
-     *        or {@code null} if no default network is currently active
-     *
-     * {@hide}
-     */
-    public NetworkInfo getProvisioningOrActiveNetworkInfo() {
-        try {
-            return mService.getProvisioningOrActiveNetworkInfo();
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /**
      * Returns the IP information for the current default network.
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
@@ -2007,24 +1985,6 @@
     }
 
     /**
-     * Signal that the captive portal check on the indicated network
-     * is complete and whether its a captive portal or not.
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
-     *
-     * @param info the {@link NetworkInfo} object for the networkType
-     *        in question.
-     * @param isCaptivePortal true/false.
-     * {@hide}
-     */
-    public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
-        try {
-            mService.captivePortalCheckCompleted(info, isCaptivePortal);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
      * Check mobile provisioning.
      *
      * @param suggestedTimeOutMs, timeout in milliseconds
@@ -2056,18 +2016,6 @@
     }
 
     /**
-     * Get the mobile redirected provisioning url.
-     * {@hide}
-     */
-    public String getMobileRedirectedProvisioningUrl() {
-        try {
-            return mService.getMobileRedirectedProvisioningUrl();
-        } catch (RemoteException e) {
-        }
-        return null;
-    }
-
-    /**
      * Set sign in error notification to visible or in visible
      *
      * @param visible
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 89d23a2..29557bb 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -53,8 +53,6 @@
     Network[] getAllNetworks();
     NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId);
 
-    NetworkInfo getProvisioningOrActiveNetworkInfo();
-
     boolean isNetworkSupported(int networkType);
 
     LinkProperties getActiveLinkProperties();
@@ -122,14 +120,10 @@
 
     boolean updateLockdownVpn();
 
-    void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal);
-
     int checkMobileProvisioning(int suggestedTimeOutMs);
 
     String getMobileProvisioningUrl();
 
-    String getMobileRedirectedProvisioningUrl();
-
     void setProvisioningNotificationVisible(boolean visible, int networkType, in String action);
 
     void setAirplaneMode(boolean enable);
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 9628bae..fe69320 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -378,6 +378,9 @@
         //
         // The HANDLE_MAGIC value MUST be kept in sync with the corresponding
         // value in the native/android/net.c NDK implementation.
+        if (netId == 0) {
+            return 0L;  // make this zero condition obvious for debugging
+        }
         final long HANDLE_MAGIC = 0xfacade;
         return (((long) netId) << 32) | HANDLE_MAGIC;
     }
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 393637e..af7a465 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -120,7 +120,6 @@
     private String mExtraInfo;
     private boolean mIsFailover;
     private boolean mIsRoaming;
-    private boolean mIsConnectedToProvisioningNetwork;
 
     /**
      * Indicates whether network connectivity is possible:
@@ -142,7 +141,6 @@
         mState = State.UNKNOWN;
         mIsAvailable = false; // until we're told otherwise, assume unavailable
         mIsRoaming = false;
-        mIsConnectedToProvisioningNetwork = false;
     }
 
     /** {@hide} */
@@ -160,7 +158,6 @@
                 mIsFailover = source.mIsFailover;
                 mIsRoaming = source.mIsRoaming;
                 mIsAvailable = source.mIsAvailable;
-                mIsConnectedToProvisioningNetwork = source.mIsConnectedToProvisioningNetwork;
             }
         }
     }
@@ -332,22 +329,6 @@
         }
     }
 
-    /** {@hide} */
-    @VisibleForTesting
-    public boolean isConnectedToProvisioningNetwork() {
-        synchronized (this) {
-            return mIsConnectedToProvisioningNetwork;
-        }
-    }
-
-    /** {@hide} */
-    @VisibleForTesting
-    public void setIsConnectedToProvisioningNetwork(boolean val) {
-        synchronized (this) {
-            mIsConnectedToProvisioningNetwork = val;
-        }
-    }
-
     /**
      * Reports the current coarse-grained state of the network.
      * @return the coarse-grained state
@@ -431,8 +412,6 @@
             append(", roaming: ").append(mIsRoaming).
             append(", failover: ").append(mIsFailover).
             append(", isAvailable: ").append(mIsAvailable).
-            append(", isConnectedToProvisioningNetwork: ").
-            append(mIsConnectedToProvisioningNetwork).
             append("]");
             return builder.toString();
         }
@@ -461,7 +440,6 @@
             dest.writeInt(mIsFailover ? 1 : 0);
             dest.writeInt(mIsAvailable ? 1 : 0);
             dest.writeInt(mIsRoaming ? 1 : 0);
-            dest.writeInt(mIsConnectedToProvisioningNetwork ? 1 : 0);
             dest.writeString(mReason);
             dest.writeString(mExtraInfo);
         }
@@ -484,7 +462,6 @@
                 netInfo.mIsFailover = in.readInt() != 0;
                 netInfo.mIsAvailable = in.readInt() != 0;
                 netInfo.mIsRoaming = in.readInt() != 0;
-                netInfo.mIsConnectedToProvisioningNetwork = in.readInt() != 0;
                 netInfo.mReason = in.readString();
                 netInfo.mExtraInfo = in.readString();
                 return netInfo;
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index ff3de2b..bb08be2 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -53,6 +53,8 @@
     public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
     /** @hide */
     public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
+    /** @hide */
+    public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
 
     /**
      * Special UID value used when collecting {@link NetworkStatsHistory} for
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 7a1aa1e..6ef1cd0 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -392,6 +392,8 @@
     final IPowerManager mService;
     final Handler mHandler;
 
+    IDeviceIdleController mIDeviceIdleController;
+
     /**
      * {@hide}
      */
@@ -892,6 +894,25 @@
     }
 
     /**
+     * Return whether the given application package name is on the device's power whitelist.
+     * Apps can be placed on the whitelist through the settings UI invoked by
+     * {@link android.provider.Settings#ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}.
+     */
+    public boolean isIgnoringBatteryOptimizations(String packageName) {
+        synchronized (this) {
+            if (mIDeviceIdleController == null) {
+                mIDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+                        ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+            }
+        }
+        try {
+            return mIDeviceIdleController.isPowerSaveWhitelistApp(packageName);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Turn off the device.
      *
      * @param confirm If true, shows a shutdown confirmation dialog.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index ef7e747..00350ec 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -362,6 +362,18 @@
     public static final String DISALLOW_SMS = "no_sms";
 
     /**
+     * Specifies if the user is not allowed to have fun. In some cases, the
+     * device owner may wish to prevent the user from experiencing amusement or
+     * joy while using the device. The default value is <code>false</code>.
+     *
+     * <p/>Key for user restrictions.
+     * <p/>Type: Boolean
+     * @see #setUserRestrictions(Bundle)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_FUN = "no_fun";
+
+    /**
      * Specifies that windows besides app windows should not be
      * created. This will block the creation of the following types of windows.
      * <li>{@link LayoutParams#TYPE_TOAST}</li>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e335f6d..dfd72c2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -579,13 +579,14 @@
     /**
      * Activity Action: Show screen for controlling which apps can ignore battery optimizations.
      * <p>
-     * In some cases, a matching Activity may not exist, so ensure you
-     * safeguard against this.
-     * <p>
-     * Input: The Intent's data URI specifies the application package name
+     * Input: Optionally, the Intent's data URI specifies the application package name
      * to be shown, with the "package" scheme.  That is "package:com.my.app".
      * <p>
      * Output: Nothing.
+     * <p>
+     * You can use {@link android.os.PowerManager#isIgnoringBatteryOptimizations
+     * PowerManager.isIgnoringBatteryOptimizations()} to determine if an application is
+     * already ignoring optimizations.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS =
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index b467f5a..13a959e 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -17,7 +17,9 @@
 package android.text.format;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.net.NetworkUtils;
+import android.net.TrafficStats;
 
 /**
  * Utility class to aid in formatting common values that are not covered
@@ -25,63 +27,88 @@
  */
 public final class Formatter {
 
+    /** {@hide} */
+    public static final int FLAG_SHORTER = 1 << 0;
+    /** {@hide} */
+    public static final int FLAG_CALCULATE_ROUNDED = 1 << 1;
+
+    /** {@hide} */
+    public static class BytesResult {
+        public final String value;
+        public final String units;
+        public final long roundedBytes;
+
+        public BytesResult(String value, String units, long roundedBytes) {
+            this.value = value;
+            this.units = units;
+            this.roundedBytes = roundedBytes;
+        }
+    }
+
     /**
      * Formats a content size to be in the form of bytes, kilobytes, megabytes, etc
      *
      * @param context Context to use to load the localized units
-     * @param number size value to be formatted
+     * @param sizeBytes size value to be formatted, in bytes
      * @return formatted string with the number
      */
-    public static String formatFileSize(Context context, long number) {
-        return formatFileSize(context, number, false);
+    public static String formatFileSize(Context context, long sizeBytes) {
+        final BytesResult res = formatBytes(context.getResources(), sizeBytes, 0);
+        return context.getString(com.android.internal.R.string.fileSizeSuffix,
+                res.value, res.units);
     }
 
     /**
      * Like {@link #formatFileSize}, but trying to generate shorter numbers
      * (showing fewer digits of precision).
      */
-    public static String formatShortFileSize(Context context, long number) {
-        return formatFileSize(context, number, true);
+    public static String formatShortFileSize(Context context, long sizeBytes) {
+        final BytesResult res = formatBytes(context.getResources(), sizeBytes, FLAG_SHORTER);
+        return context.getString(com.android.internal.R.string.fileSizeSuffix,
+                res.value, res.units);
     }
 
-    private static String formatFileSize(Context context, long number, boolean shorter) {
-        if (context == null) {
-            return "";
-        }
-
-        float result = number;
+    /** {@hide} */
+    public static BytesResult formatBytes(Resources res, long sizeBytes, int flags) {
+        float result = sizeBytes;
         int suffix = com.android.internal.R.string.byteShort;
+        long mult = 1;
         if (result > 900) {
             suffix = com.android.internal.R.string.kilobyteShort;
+            mult = TrafficStats.KB_IN_BYTES;
             result = result / 1024;
         }
         if (result > 900) {
             suffix = com.android.internal.R.string.megabyteShort;
+            mult = TrafficStats.MB_IN_BYTES;
             result = result / 1024;
         }
         if (result > 900) {
             suffix = com.android.internal.R.string.gigabyteShort;
+            mult = TrafficStats.GB_IN_BYTES;
             result = result / 1024;
         }
         if (result > 900) {
             suffix = com.android.internal.R.string.terabyteShort;
+            mult = TrafficStats.TB_IN_BYTES;
             result = result / 1024;
         }
         if (result > 900) {
             suffix = com.android.internal.R.string.petabyteShort;
+            mult = TrafficStats.PB_IN_BYTES;
             result = result / 1024;
         }
         String value;
         if (result < 1) {
             value = String.format("%.2f", result);
         } else if (result < 10) {
-            if (shorter) {
+            if ((flags & FLAG_SHORTER) != 0) {
                 value = String.format("%.1f", result);
             } else {
                 value = String.format("%.2f", result);
             }
         } else if (result < 100) {
-            if (shorter) {
+            if ((flags & FLAG_SHORTER) != 0) {
                 value = String.format("%.0f", result);
             } else {
                 value = String.format("%.2f", result);
@@ -89,9 +116,14 @@
         } else {
             value = String.format("%.0f", result);
         }
-        return context.getResources().
-            getString(com.android.internal.R.string.fileSizeSuffix,
-                      value, context.getString(suffix));
+        final String units = res.getString(suffix);
+        final long roundedBytes;
+        if ((flags & FLAG_CALCULATE_ROUNDED) != 0) {
+            roundedBytes = (long) (Double.parseDouble(value) * mult);
+        } else {
+            roundedBytes = 0;
+        }
+        return new BytesResult(value, units, roundedBytes);
     }
 
     /**
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index c40f11f..93a156b 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -165,7 +165,7 @@
 
     /**
      * The text associated with this span is a series of characters that have to
-     * be read verbatim. The engine will attempt to ready out any character like
+     * be read verbatim. The engine will attempt to read out any character like
      * punctuation but excluding whitespace. {@link #ARG_VERBATIM} is required.
      * Also accepts the arguments {@link #ARG_GENDER},
      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
diff --git a/core/java/android/transition/Explode.java b/core/java/android/transition/Explode.java
index 788676a..3445ef2 100644
--- a/core/java/android/transition/Explode.java
+++ b/core/java/android/transition/Explode.java
@@ -90,7 +90,7 @@
         float startY = endY + mTempLoc[1];
 
         return TranslationAnimationCreator.createAnimation(view, endValues, bounds.left, bounds.top,
-                startX, startY, endX, endY, sDecelerate);
+                startX, startY, endX, endY, sDecelerate, this);
     }
 
     @Override
@@ -119,7 +119,7 @@
         endY += mTempLoc[1];
 
         return TranslationAnimationCreator.createAnimation(view, startValues,
-                viewPosX, viewPosY, startX, startY, endX, endY, sAccelerate);
+                viewPosX, viewPosY, startX, startY, endX, endY, sAccelerate, this);
     }
 
     private void calculateOut(View sceneRoot, Rect bounds, int[] outVector) {
diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java
index be1d907..9063b43 100644
--- a/core/java/android/transition/Slide.java
+++ b/core/java/android/transition/Slide.java
@@ -231,7 +231,7 @@
         float startY = mSlideCalculator.getGoneY(sceneRoot, view);
         return TranslationAnimationCreator
                 .createAnimation(view, endValues, position[0], position[1],
-                        startX, startY, endX, endY, sDecelerate);
+                        startX, startY, endX, endY, sDecelerate, this);
     }
 
     @Override
@@ -247,6 +247,6 @@
         float endY = mSlideCalculator.getGoneY(sceneRoot, view);
         return TranslationAnimationCreator
                 .createAnimation(view, startValues, position[0], position[1],
-                        startX, startY, endX, endY, sAccelerate);
+                        startX, startY, endX, endY, sAccelerate, this);
     }
 }
diff --git a/core/java/android/transition/TranslationAnimationCreator.java b/core/java/android/transition/TranslationAnimationCreator.java
index de71fd7..1554975 100644
--- a/core/java/android/transition/TranslationAnimationCreator.java
+++ b/core/java/android/transition/TranslationAnimationCreator.java
@@ -22,6 +22,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.graphics.Path;
+import android.transition.Transition.TransitionListener;
 import android.view.View;
 
 /**
@@ -48,7 +49,8 @@
      * a previous interruption, in which case it moves from the current position to (endX, endY).
      */
     static Animator createAnimation(View view, TransitionValues values, int viewPosX, int viewPosY,
-            float startX, float startY, float endX, float endY, TimeInterpolator interpolator) {
+            float startX, float startY, float endX, float endY, TimeInterpolator interpolator,
+            Transition transition) {
         float terminalX = view.getTranslationX();
         float terminalY = view.getTranslationY();
         int[] startPosition = (int[]) values.view.getTag(R.id.transitionPosition);
@@ -73,13 +75,15 @@
 
         TransitionPositionListener listener = new TransitionPositionListener(view, values.view,
                 startPosX, startPosY, terminalX, terminalY);
+        transition.addListener(listener);
         anim.addListener(listener);
         anim.addPauseListener(listener);
         anim.setInterpolator(interpolator);
         return anim;
     }
 
-    private static class TransitionPositionListener extends AnimatorListenerAdapter {
+    private static class TransitionPositionListener extends AnimatorListenerAdapter implements
+            TransitionListener {
 
         private final View mViewInHierarchy;
         private final View mMovingView;
@@ -117,8 +121,6 @@
 
         @Override
         public void onAnimationEnd(Animator animator) {
-            mMovingView.setTranslationX(mTerminalX);
-            mMovingView.setTranslationY(mTerminalY);
         }
 
         @Override
@@ -134,6 +136,28 @@
             mMovingView.setTranslationX(mPausedX);
             mMovingView.setTranslationY(mPausedY);
         }
+
+        @Override
+        public void onTransitionStart(Transition transition) {
+        }
+
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            mMovingView.setTranslationX(mTerminalX);
+            mMovingView.setTranslationY(mTerminalY);
+        }
+
+        @Override
+        public void onTransitionCancel(Transition transition) {
+        }
+
+        @Override
+        public void onTransitionPause(Transition transition) {
+        }
+
+        @Override
+        public void onTransitionResume(Transition transition) {
+        }
     }
 
 }
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index bac668a..8b74a1e 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -557,7 +557,7 @@
                 if (mIsForcedVisibility) {
                     mView.setTransitionAlpha(0);
                 } else {
-                    mView.setTransitionVisibility(mFinalVisibility);
+                    mView.setVisibility(mFinalVisibility);
                 }
             }
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0df8ea9..fd3ee4f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -56,6 +56,8 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -95,6 +97,7 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Checkable;
+import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
 
 import static android.os.Build.VERSION_CODES.*;
@@ -4274,23 +4277,33 @@
                             PROVIDER_BACKGROUND));
                     break;
                 case R.styleable.View_foreground:
-                    setForeground(a.getDrawable(attr));
+                    if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+                        setForeground(a.getDrawable(attr));
+                    }
                     break;
                 case R.styleable.View_foregroundGravity:
-                    setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
+                    if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
+                    }
                     break;
                 case R.styleable.View_foregroundTintMode:
-                    setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
+                    if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
+                    }
                     break;
                 case R.styleable.View_foregroundTint:
-                    setForegroundTintList(a.getColorStateList(attr));
+                    if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+                        setForegroundTintList(a.getColorStateList(attr));
+                    }
                     break;
                 case R.styleable.View_foregroundInsidePadding:
-                    if (mForegroundInfo == null) {
-                        mForegroundInfo = new ForegroundInfo();
+                    if (targetSdkVersion >= VERSION_CODES.MNC || this instanceof FrameLayout) {
+                        if (mForegroundInfo == null) {
+                            mForegroundInfo = new ForegroundInfo();
+                        }
+                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
+                                mForegroundInfo.mInsidePadding);
                     }
-                    mForegroundInfo.mInsidePadding = a.getBoolean(attr,
-                            mForegroundInfo.mInsidePadding);
                     break;
                 case R.styleable.View_scrollIndicators:
                     final int scrollIndicators =
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index bd45007..f18b7ac 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -80,12 +80,18 @@
 
     /**
      * The interpolator of the underlying Animator object. By default, we don't set the interpolator
-     * on the Animator and just use its default interpolator. If the interpolator is set to a
-     * non-null value on this Animator, then we use the interpolator that it was set to.
+     * on the Animator and just use its default interpolator. If the interpolator is ever set on
+     * this Animator, then we use the interpolator that it was set to.
      */
     private TimeInterpolator mInterpolator;
 
     /**
+     * A flag indicating whether the interpolator has been set on this object. If not, we don't set
+     * the interpolator on the underlying Animator, but instead just use its default interpolator.
+     */
+    private boolean mInterpolatorSet = false;
+
+    /**
      * Listener for the lifecycle events of the underlying ValueAnimator object.
      */
     private Animator.AnimatorListener mListener = null;
@@ -332,6 +338,7 @@
      * @return This object, allowing calls to methods in this class to be chained.
      */
     public ViewPropertyAnimator setInterpolator(TimeInterpolator interpolator) {
+        mInterpolatorSet = true;
         mInterpolator = interpolator;
         return this;
     }
@@ -342,7 +349,7 @@
      * @return The timing interpolator for this animation.
      */
     public TimeInterpolator getInterpolator() {
-        if (mInterpolator != null) {
+        if (mInterpolatorSet) {
             return mInterpolator;
         } else {
             // Just return the default from ValueAnimator, since that's what we'd get if
@@ -890,7 +897,7 @@
         if (mDurationSet) {
             animator.setDuration(mDuration);
         }
-        if (mInterpolator != null) {
+        if (mInterpolatorSet) {
             animator.setInterpolator(mInterpolator);
         }
         animator.start();
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index 382a266..410d39c 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -52,11 +52,9 @@
     /** Default scaling value for caption fonts. */
     private static final float DEFAULT_FONT_SCALE = 1;
 
-    private final ArrayList<CaptioningChangeListener>
-            mListeners = new ArrayList<CaptioningChangeListener>();
-    private final Handler mHandler = new Handler();
-
+    private final ArrayList<CaptioningChangeListener> mListeners = new ArrayList<>();
     private final ContentResolver mContentResolver;
+    private final ContentObserver mContentObserver;
 
     /**
      * Creates a new captioning manager for the specified context.
@@ -65,6 +63,9 @@
      */
     public CaptioningManager(Context context) {
         mContentResolver = context.getContentResolver();
+
+        final Handler handler = new Handler(context.getMainLooper());
+        mContentObserver = new MyContentObserver(handler);
     }
 
     /**
@@ -220,7 +221,15 @@
         }
     }
 
-    private final ContentObserver mContentObserver = new ContentObserver(mHandler) {
+    private class MyContentObserver extends ContentObserver {
+        private final Handler mHandler;
+
+        public MyContentObserver(Handler handler) {
+            super(handler);
+
+            mHandler = handler;
+        }
+
         @Override
         public void onChange(boolean selfChange, Uri uri) {
             final String uriPath = uri.getPath();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index cf6a018..f89ee91 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -244,15 +244,6 @@
 
     final CursorAnchorInfoNotifier mCursorAnchorInfoNotifier = new CursorAnchorInfoNotifier();
 
-    private final Runnable mHideFloatingToolbar = new Runnable() {
-        @Override
-        public void run() {
-            if (mTextActionMode != null) {
-                mTextActionMode.hide(ActionMode.DEFAULT_HIDE_DURATION);
-            }
-        }
-    };
-
     private final Runnable mShowFloatingToolbar = new Runnable() {
         @Override
         public void run() {
@@ -389,7 +380,6 @@
             mTextView.removeCallbacks(mInsertionActionModeRunnable);
         }
 
-        mTextView.removeCallbacks(mHideFloatingToolbar);
         mTextView.removeCallbacks(mShowFloatingToolbar);
 
         destroyDisplayListsData();
@@ -1248,14 +1238,12 @@
     private void hideFloatingToolbar() {
         if (mTextActionMode != null) {
             mTextView.removeCallbacks(mShowFloatingToolbar);
-            // Delay the "hide" a little bit just in case a "show" will happen almost immediately.
-            mTextView.postDelayed(mHideFloatingToolbar, 100);
+            mTextActionMode.hide(ActionMode.DEFAULT_HIDE_DURATION);
         }
     }
 
     private void showFloatingToolbar() {
         if (mTextActionMode != null) {
-            mTextView.removeCallbacks(mHideFloatingToolbar);
             // Delay "show" so it doesn't interfere with click confirmations
             // or double-clicks that could "dismiss" the floating toolbar.
             int delay = ViewConfiguration.getDoubleTapTimeout();
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 8ace0f3..2ea2667 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -26,7 +26,6 @@
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -148,6 +147,9 @@
     // Clear me after use.
     private final ArrayList<View> mTempViews = new ArrayList<View>();
 
+    // Used to hold views that will be removed while we have an expanded action view.
+    private final ArrayList<View> mHiddenViews = new ArrayList<>();
+
     private final int[] mTempMargins = new int[2];
 
     private OnMenuItemClickListener mOnMenuItemClickListener;
@@ -435,12 +437,12 @@
     public void setLogo(Drawable drawable) {
         if (drawable != null) {
             ensureLogoView();
-            if (mLogoView.getParent() == null) {
-                addSystemView(mLogoView);
-                updateChildVisibilityForExpandedActionView(mLogoView);
+            if (!isChildOrHidden(mLogoView)) {
+                addSystemView(mLogoView, true);
             }
-        } else if (mLogoView != null && mLogoView.getParent() != null) {
+        } else if (mLogoView != null && isChildOrHidden(mLogoView)) {
             removeView(mLogoView);
+            mHiddenViews.remove(mLogoView);
         }
         if (mLogoView != null) {
             mLogoView.setImageDrawable(drawable);
@@ -577,12 +579,12 @@
                     mTitleTextView.setTextColor(mTitleTextColor);
                 }
             }
-            if (mTitleTextView.getParent() == null) {
-                addSystemView(mTitleTextView);
-                updateChildVisibilityForExpandedActionView(mTitleTextView);
+            if (!isChildOrHidden(mTitleTextView)) {
+                addSystemView(mTitleTextView, true);
             }
-        } else if (mTitleTextView != null && mTitleTextView.getParent() != null) {
+        } else if (mTitleTextView != null && isChildOrHidden(mTitleTextView)) {
             removeView(mTitleTextView);
+            mHiddenViews.remove(mTitleTextView);
         }
         if (mTitleTextView != null) {
             mTitleTextView.setText(title);
@@ -631,12 +633,12 @@
                     mSubtitleTextView.setTextColor(mSubtitleTextColor);
                 }
             }
-            if (mSubtitleTextView.getParent() == null) {
-                addSystemView(mSubtitleTextView);
-                updateChildVisibilityForExpandedActionView(mSubtitleTextView);
+            if (!isChildOrHidden(mSubtitleTextView)) {
+                addSystemView(mSubtitleTextView, true);
             }
-        } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) {
+        } else if (mSubtitleTextView != null && isChildOrHidden(mSubtitleTextView)) {
             removeView(mSubtitleTextView);
+            mHiddenViews.remove(mSubtitleTextView);
         }
         if (mSubtitleTextView != null) {
             mSubtitleTextView.setText(subtitle);
@@ -772,12 +774,12 @@
     public void setNavigationIcon(@Nullable Drawable icon) {
         if (icon != null) {
             ensureNavButtonView();
-            if (mNavButtonView.getParent() == null) {
-                addSystemView(mNavButtonView);
-                updateChildVisibilityForExpandedActionView(mNavButtonView);
+            if (!isChildOrHidden(mNavButtonView)) {
+                addSystemView(mNavButtonView, true);
             }
-        } else if (mNavButtonView != null && mNavButtonView.getParent() != null) {
+        } else if (mNavButtonView != null && isChildOrHidden(mNavButtonView)) {
             removeView(mNavButtonView);
+            mHiddenViews.remove(mNavButtonView);
         }
         if (mNavButtonView != null) {
             mNavButtonView.setImageDrawable(icon);
@@ -866,7 +868,7 @@
             final LayoutParams lp = generateDefaultLayoutParams();
             lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
             mMenuView.setLayoutParams(lp);
-            addSystemView(mMenuView);
+            addSystemView(mMenuView, false);
         }
     }
 
@@ -1041,7 +1043,7 @@
         }
     }
 
-    private void addSystemView(View v) {
+    private void addSystemView(View v, boolean allowHide) {
         final ViewGroup.LayoutParams vlp = v.getLayoutParams();
         final LayoutParams lp;
         if (vlp == null) {
@@ -1052,7 +1054,13 @@
             lp = (LayoutParams) vlp;
         }
         lp.mViewType = LayoutParams.SYSTEM;
-        addView(v, lp);
+
+        if (allowHide && mExpandedActionView != null) {
+            v.setLayoutParams(lp);
+            mHiddenViews.add(v);
+        } else {
+            addView(v, lp);
+        }
     }
 
     @Override
@@ -1741,22 +1749,30 @@
         return mWrapper;
     }
 
-    private void setChildVisibilityForExpandedActionView(boolean expand) {
+    void removeChildrenForExpandedActionView() {
         final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
+        // Go backwards since we're removing from the list
+        for (int i = childCount - 1; i >= 0; i--) {
             final View child = getChildAt(i);
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
-                child.setVisibility(expand ? GONE : VISIBLE);
+                removeViewAt(i);
+                mHiddenViews.add(child);
             }
         }
     }
 
-    private void updateChildVisibilityForExpandedActionView(View child) {
-        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-        if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
-            child.setVisibility(mExpandedActionView != null ? GONE : VISIBLE);
+    void addChildrenForExpandedActionView() {
+        final int count = mHiddenViews.size();
+        // Re-add in reverse order since we removed in reverse order
+        for (int i = count - 1; i >= 0; i--) {
+            addView(mHiddenViews.get(i));
         }
+        mHiddenViews.clear();
+    }
+
+    private boolean isChildOrHidden(View child) {
+        return child.getParent() == this || mHiddenViews.contains(child);
     }
 
     /**
@@ -1971,7 +1987,7 @@
                 addView(mExpandedActionView);
             }
 
-            setChildVisibilityForExpandedActionView(true);
+            removeChildrenForExpandedActionView();
             requestLayout();
             item.setActionViewExpanded(true);
 
@@ -1994,7 +2010,7 @@
             removeView(mCollapseButtonView);
             mExpandedActionView = null;
 
-            setChildVisibilityForExpandedActionView(false);
+            addChildrenForExpandedActionView();
             mCurrentExpandedItem = null;
             requestLayout();
             item.setActionViewExpanded(false);
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
new file mode 100644
index 0000000..b520384
--- /dev/null
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.app;
+
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * Utility method for dealing with the assistant aspects of
+ * {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}.
+ */
+public class AssistUtils {
+
+    private static final String TAG = "AssistUtils";
+
+    private final Context mContext;
+    private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
+
+    public AssistUtils(Context context) {
+        mContext = context;
+        mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
+                ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+    }
+
+    public void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback) {
+        try {
+            mVoiceInteractionManagerService.showSessionForActiveService(showCallback);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call showSessionForActiveService", e);
+        }
+    }
+
+    public void launchVoiceAssistFromKeyguard() {
+        try {
+            mVoiceInteractionManagerService.launchVoiceAssistFromKeyguard();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call launchVoiceAssistFromKeyguard", e);
+        }
+    }
+
+    public boolean activeServiceSupportsAssistGesture() {
+        try {
+            return mVoiceInteractionManagerService != null
+                    && mVoiceInteractionManagerService.activeServiceSupportsAssist();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
+            return false;
+        }
+    }
+
+    public boolean activeServiceSupportsLaunchFromKeyguard() {
+        try {
+            return mVoiceInteractionManagerService != null
+                    && mVoiceInteractionManagerService.activeServiceSupportsLaunchFromKeyguard();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call activeServiceSupportsLaunchFromKeyguard", e);
+            return false;
+        }
+    }
+
+    public ComponentName getActiveServiceComponentName() {
+        try {
+            return mVoiceInteractionManagerService.getActiveServiceComponentName();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
+            return null;
+        }
+    }
+
+    public boolean isSessionRunning() {
+        try {
+            return mVoiceInteractionManagerService != null
+                    && mVoiceInteractionManagerService.isSessionRunning();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call isSessionRunning", e);
+            return false;
+        }
+    }
+
+    public void hideCurrentSession() {
+        try {
+            mVoiceInteractionManagerService.hideCurrentSession();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call hideCurrentSession", e);
+        }
+    }
+
+    public ComponentName getAssistComponentForUser(int userId) {
+        final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                Settings.Secure.ASSISTANT, userId);
+        if (setting != null) {
+            return ComponentName.unflattenFromString(setting);
+        }
+
+        // Fallback to keep backward compatible behavior when there is no user setting.
+        if (activeServiceSupportsAssistGesture()) {
+            return getActiveServiceComponentName();
+        }
+
+        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, false, userId);
+        if (intent != null) {
+            return intent.getComponent();
+        }
+
+        return null;
+    }
+
+}
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 34b9dcb..2b162af 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -83,7 +83,9 @@
 
     @Override
     public void setCustomView(View view, LayoutParams layoutParams) {
-        view.setLayoutParams(layoutParams);
+        if (view != null) {
+            view.setLayoutParams(layoutParams);
+        }
         mDecorToolbar.setCustomView(view);
     }
 
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 2539a35..f81658e 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -24,6 +24,7 @@
 import android.os.IBinder;
 import android.os.Process;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.util.Log;
 import android.util.Slog;
 import com.android.internal.logging.AndroidConfig;
@@ -269,11 +270,11 @@
             throws ZygoteInit.MethodAndArgsCaller {
         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
 
+        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
         redirectLogStreams();
 
         commonInit();
         nativeZygoteInit();
-
         applicationInit(targetSdkVersion, argv, classLoader);
     }
 
@@ -318,6 +319,9 @@
             return;
         }
 
+        // The end of of the RuntimeInit event (see #zygoteInit).
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
         // Remaining arguments are passed to the start class's static main
         invokeStaticMain(args.startClass, args.startArgs, classLoader);
     }
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 1e7ee5a..4f6d781 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -17,6 +17,7 @@
 package com.android.internal.os;
 
 
+import android.os.Trace;
 import dalvik.system.ZygoteHooks;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -88,6 +89,13 @@
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                   instructionSet, appDataDir);
+        // Enable tracing as soon as possible for the child process.
+        if (pid == 0) {
+            Trace.setTracingEnabled(true);
+
+            // Note that this event ends at the end of handleChildProc,
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
+        }
         VM_HOOKS.postForkCommon();
         return pid;
     }
@@ -124,6 +132,10 @@
         VM_HOOKS.preFork();
         int pid = nativeForkSystemServer(
                 uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
+        // Enable tracing as soon as we enter the system_server.
+        if (pid == 0) {
+            Trace.setTracingEnabled(true);
+        }
         VM_HOOKS.postForkCommon();
         return pid;
     }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 969d236..1a0345b 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -27,6 +27,7 @@
 import android.os.Process;
 import android.os.SELinux;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.Log;
@@ -711,7 +712,6 @@
     private void handleChildProc(Arguments parsedArgs,
             FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
             throws ZygoteInit.MethodAndArgsCaller {
-
         /**
          * By the time we get here, the native code has closed the two actual Zygote
          * socket connections, and substituted /dev/null in their place.  The LocalSocket
@@ -740,6 +740,8 @@
             Process.setArgV0(parsedArgs.niceName);
         }
 
+        // End of the postFork event.
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         if (parsedArgs.invokeWith != null) {
             WrapperInit.execApplication(parsedArgs.invokeWith,
                     parsedArgs.niceName, parsedArgs.targetSdkVersion,
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 661dce1..99c12776 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -48,12 +48,14 @@
     private final Runnable mMovingOff = new Runnable() {
         public void run() {
             mFloatingToolbarVisibilityHelper.setMoving(false);
+            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
         }
     };
 
     private final Runnable mHideOff = new Runnable() {
         public void run() {
             mFloatingToolbarVisibilityHelper.setHideRequested(false);
+            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
         }
     };
 
@@ -87,6 +89,7 @@
                     }
                 });
         mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar);
+        mFloatingToolbarVisibilityHelper.activate();
     }
 
     @Override
@@ -108,8 +111,7 @@
     public void invalidate() {
         checkToolbarInitialized();
         mCallback.onPrepareActionMode(this, mMenu);
-        mFloatingToolbar.updateLayout();
-        invalidateContentRect();
+        invalidateContentRect();  // Will re-layout and show the toolbar if necessary.
     }
 
     @Override
@@ -131,44 +133,43 @@
 
         mContentRectOnWindow.set(mContentRect);
         mContentRectOnWindow.offset(mViewPosition[0], mViewPosition[1]);
-        // Make sure that content rect is not out of the view's visible bounds.
-        mContentRectOnWindow.set(
-                Math.max(mContentRectOnWindow.left, mViewRect.left),
-                Math.max(mContentRectOnWindow.top, mViewRect.top),
-                Math.min(mContentRectOnWindow.right, mViewRect.right),
-                Math.min(mContentRectOnWindow.bottom, mViewRect.bottom));
-
-        if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) {
-            if (!mPreviousContentRectOnWindow.isEmpty()) {
-                notifyContentRectMoving();
-            }
-            mFloatingToolbar.setContentRect(mContentRectOnWindow);
-            mFloatingToolbar.updateLayout();
-        }
-        mPreviousContentRectOnWindow.set(mContentRectOnWindow);
 
         if (isContentRectWithinBounds()) {
             mFloatingToolbarVisibilityHelper.setOutOfBounds(false);
+            // Make sure that content rect is not out of the view's visible bounds.
+            mContentRectOnWindow.set(
+                    Math.max(mContentRectOnWindow.left, mViewRect.left),
+                    Math.max(mContentRectOnWindow.top, mViewRect.top),
+                    Math.min(mContentRectOnWindow.right, mViewRect.right),
+                    Math.min(mContentRectOnWindow.bottom, mViewRect.bottom));
+
+            if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) {
+                // Content rect is moving.
+                mOriginatingView.removeCallbacks(mMovingOff);
+                mFloatingToolbarVisibilityHelper.setMoving(true);
+                mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY);
+
+                mFloatingToolbar.setContentRect(mContentRectOnWindow);
+                mFloatingToolbar.updateLayout();
+            }
         } else {
             mFloatingToolbarVisibilityHelper.setOutOfBounds(true);
+            mContentRectOnWindow.setEmpty();
         }
+        mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
+
+        mPreviousContentRectOnWindow.set(mContentRectOnWindow);
     }
 
     private boolean isContentRectWithinBounds() {
-       mScreenRect.set(
-           0,
-           0,
-           mContext.getResources().getDisplayMetrics().widthPixels,
-           mContext.getResources().getDisplayMetrics().heightPixels);
+        mScreenRect.set(
+            0,
+            0,
+            mContext.getResources().getDisplayMetrics().widthPixels,
+            mContext.getResources().getDisplayMetrics().heightPixels);
 
-       return Rect.intersects(mContentRectOnWindow, mScreenRect)
-           && Rect.intersects(mContentRectOnWindow, mViewRect);
-    }
-
-    private void notifyContentRectMoving() {
-        mOriginatingView.removeCallbacks(mMovingOff);
-        mFloatingToolbarVisibilityHelper.setMoving(true);
-        mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY);
+        return Rect.intersects(mContentRectOnWindow, mScreenRect)
+            && Rect.intersects(mContentRectOnWindow, mViewRect);
     }
 
     @Override
@@ -184,6 +185,7 @@
             mHideOff.run();
         } else {
             mFloatingToolbarVisibilityHelper.setHideRequested(true);
+            mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
             mOriginatingView.postDelayed(mHideOff, duration);
         }
     }
@@ -221,7 +223,7 @@
     }
 
     /**
-     * @throws IlllegalStateException
+     * @throws IllegalStateException
      */
     private void checkToolbarInitialized() {
         Preconditions.checkState(mFloatingToolbar != null);
@@ -229,13 +231,14 @@
     }
 
     private void reset() {
+        mFloatingToolbarVisibilityHelper.deactivate();
         mOriginatingView.removeCallbacks(mMovingOff);
         mOriginatingView.removeCallbacks(mHideOff);
     }
 
 
     /**
-     * A helper that shows/hides the floating toolbar depending on certain states.
+     * A helper for showing/hiding the floating toolbar depending on certain states.
      */
     private static final class FloatingToolbarVisibilityHelper {
 
@@ -245,29 +248,45 @@
         private boolean mMoving;
         private boolean mOutOfBounds;
 
+        private boolean mActive;
+
         public FloatingToolbarVisibilityHelper(FloatingToolbar toolbar) {
             mToolbar = Preconditions.checkNotNull(toolbar);
         }
 
+        public void activate() {
+            mHideRequested = false;
+            mMoving = false;
+            mOutOfBounds = false;
+
+            mActive = true;
+        }
+
+        public void deactivate() {
+            mActive = false;
+            mToolbar.dismiss();
+        }
+
         public void setHideRequested(boolean hide) {
             mHideRequested = hide;
-            updateToolbarVisibility();
         }
 
         public void setMoving(boolean moving) {
             mMoving = moving;
-            updateToolbarVisibility();
         }
 
         public void setOutOfBounds(boolean outOfBounds) {
             mOutOfBounds = outOfBounds;
-            updateToolbarVisibility();
         }
 
-        private void updateToolbarVisibility() {
+        public void updateToolbarVisibility() {
+            if (!mActive) {
+                return;
+            }
+
             if (mHideRequested || mMoving || mOutOfBounds) {
                 mToolbar.hide();
-            } else if (mToolbar.isHidden()) {
+            } else {
                 mToolbar.show();
             }
         }
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 2d0989f..53ebc23 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -37,7 +37,6 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
-import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.animation.Animation;
 import android.view.animation.AnimationSet;
@@ -436,8 +435,6 @@
                 // The "show" animation will make this visible.
                 mContentContainer.setAlpha(0);
             }
-            refreshViewPort();
-            updateOverflowHeight(contentRect.top - (mMarginVertical * 2) - mViewPort.top);
             refreshCoordinatesAndOverflowDirection(contentRect);
             preparePopupContent();
             mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y);
@@ -501,7 +498,6 @@
             }
 
             cancelOverflowAnimations();
-            refreshViewPort();
             refreshCoordinatesAndOverflowDirection(contentRect);
             preparePopupContent();
             mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight());
@@ -529,28 +525,65 @@
         }
 
         private void refreshCoordinatesAndOverflowDirection(Rect contentRect) {
-            // NOTE: Ensure that mViewPort has been refreshed before this.
+            refreshViewPort();
+
+            int availableHeightAboveContent =
+                    contentRect.top - mViewPort.top - 2 * mMarginVertical;
+            int availableHeightBelowContent =
+                    mViewPort.bottom - contentRect.bottom - 2 * mMarginVertical;
+            int availableHeightThroughContent =
+                    mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin();
 
             int x = contentRect.centerX() - getWidth() / 2;
-            int y;
-            if (contentRect.top - getHeight() > mViewPort.top) {
-                y = contentRect.top - getHeight();
-                mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP;
-            } else if (contentRect.top - getToolbarHeightWithVerticalMargin() > mViewPort.top) {
-                y = contentRect.top - getToolbarHeightWithVerticalMargin();
-                mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
-            } else {
-                y = contentRect.bottom;
-                mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
-            }
-
             // Update x so that the toolbar isn't rendered behind the nav bar in landscape.
             x = Math.max(0, Math.min(x, mViewPort.right - getWidth()));
 
-            mCoords.set(x, y);
-            if (mOverflowPanel != null) {
+            int y;
+            if (mOverflowPanel == null) {  // There is no overflow.
+                if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin()) {
+                    // There is enough space at the top of the content.
+                    y = contentRect.top - getToolbarHeightWithVerticalMargin();
+                } else if (availableHeightBelowContent > getToolbarHeightWithVerticalMargin()) {
+                    // There is enough space at the bottom of the content.
+                    y = contentRect.bottom;
+                } else {
+                    // Not enough space. Prefer to position as high as possible.
+                    y = Math.max(
+                            mViewPort.top,
+                            contentRect.top - getToolbarHeightWithVerticalMargin());
+                }
+            } else {  // There is an overflow.
+                if (availableHeightAboveContent > mOverflowPanel.getMinimumHeight()) {
+                    // There is enough space at the top of the content rect for the overflow.
+                    // Position above and open upwards.
+                    updateOverflowHeight(availableHeightAboveContent);
+                    y = contentRect.top - getHeight();
+                    mOverflowDirection = OVERFLOW_DIRECTION_UP;
+                } else if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin()
+                        && availableHeightThroughContent > mOverflowPanel.getMinimumHeight()) {
+                    // There is enough space at the top of the content rect for the main panel
+                    // but not the overflow.
+                    // Position above but open downwards.
+                    updateOverflowHeight(availableHeightThroughContent);
+                    y = contentRect.top - getToolbarHeightWithVerticalMargin();
+                    mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
+                } else if (availableHeightBelowContent > mOverflowPanel.getMinimumHeight()) {
+                    // There is enough space at the bottom of the content rect for the overflow.
+                    // Position below and open downwards.
+                    updateOverflowHeight(availableHeightBelowContent);
+                    y = contentRect.bottom;
+                    mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
+                } else {
+                    // Not enough space.
+                    // Position at the bottom of the view port and open upwards.
+                    updateOverflowHeight(mViewPort.height());
+                    y = mViewPort.bottom - getHeight();
+                    mOverflowDirection = OVERFLOW_DIRECTION_UP;
+                }
                 mOverflowPanel.setOverflowDirection(mOverflowDirection);
             }
+
+            mCoords.set(x, y);
         }
 
         private int getToolbarHeightWithVerticalMargin() {
@@ -837,13 +870,7 @@
 
 
         private void refreshViewPort() {
-            mParent.getGlobalVisibleRect(mViewPort);
-            WindowInsets windowInsets = mParent.getRootWindowInsets();
-            mViewPort.set(
-                    mViewPort.left + windowInsets.getStableInsetLeft(),
-                    mViewPort.top + windowInsets.getStableInsetTop(),
-                    mViewPort.right - windowInsets.getStableInsetRight(),
-                    mViewPort.bottom - windowInsets.getStableInsetBottom());
+            mParent.getWindowVisibleDisplayFrame(mViewPort);
         }
 
         private int getToolbarWidth(int suggestedWidth) {
@@ -1139,6 +1166,12 @@
             setListViewHeight();
         }
 
+        public int getMinimumHeight() {
+            return mContentView.getContext().getResources().
+                    getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height)
+                    + getEstimatedToolbarHeight(mContentView.getContext());
+        }
+
         /**
          * Returns the content view of the overflow.
          */
@@ -1173,13 +1206,18 @@
                     getDimensionPixelSize(R.dimen.floating_toolbar_maximum_overflow_height);
             int minHeight = mContentView.getContext().getResources().
                     getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height);
-            int availableHeight = mSuggestedHeight - (mSuggestedHeight % itemHeight)
+            int suggestedListViewHeight = mSuggestedHeight - (mSuggestedHeight % itemHeight)
                     - itemHeight;  // reserve space for the back button.
             ViewGroup.LayoutParams params = mListView.getLayoutParams();
-            if (availableHeight >= minHeight) {
-                params.height = Math.min(Math.min(availableHeight, maxHeight), height);
-            } else {
+            if (suggestedListViewHeight <= 0) {
+                // Invalid height. Use the maximum height available.
                 params.height = Math.min(maxHeight, height);
+            } else if (suggestedListViewHeight < minHeight) {
+                // Height is smaller than minimum allowed. Use minimum height.
+                params.height = minHeight;
+            } else {
+                // Use the suggested height. Cap it at the maximum available height.
+                params.height = Math.min(Math.min(suggestedListViewHeight, maxHeight), height);
             }
             mListView.setLayoutParams(params);
         }
@@ -1360,6 +1398,7 @@
         PopupWindow popupWindow = new PopupWindow(popupContentHolder);
         popupWindow.setWindowLayoutType(
                 WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
+        popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
         popupWindow.setAnimationStyle(0);
         popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
         content.setLayoutParams(new ViewGroup.LayoutParams(
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 2229071..304de8c 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -371,8 +371,8 @@
         realCount = count;
     }
 
-    jobject chainingBuf = mEnv->CallObjectMethod(mInBuf, gInputByteBufferClassInfo.mGetMethod, mByteArray, 0,
-            realCount);
+    jobject chainingBuf = mEnv->CallObjectMethod(mInBuf, gInputByteBufferClassInfo.mGetMethod,
+            mByteArray, 0, realCount);
     mEnv->DeleteLocalRef(chainingBuf);
 
     if (mEnv->ExceptionCheck()) {
@@ -630,8 +630,10 @@
     bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1);
 
     // TODO: handle lens shading map, etc. conversions for other raw buffer sizes.
-    uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>());
-    uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>());
+    uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 :
+            TIFF_IFD_0)->getData<uint32_t>());
+    uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 :
+            TIFF_IFD_0)->getData<uint32_t>());
 
     if (width < 0 || metadataWidth != static_cast<uint32_t>(width)) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \
@@ -641,7 +643,8 @@
 
     if (height < 0 || metadataHeight != static_cast<uint32_t>(height)) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \
-                        "Metadata height %d doesn't match image height %d", metadataHeight, height);
+                        "Metadata height %d doesn't match image height %d",
+                        metadataHeight, height);
         return false;
     }
 
@@ -1428,7 +1431,11 @@
     }
 
     {
-        // Setup opcode List 2
+        // Set up opcode List 2
+        OpcodeListBuilder builder;
+        status_t err = OK;
+
+        // Set up lens shading map
         camera_metadata_entry entry1 =
                 characteristics.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
 
@@ -1444,34 +1451,52 @@
                 results.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
 
         if (entry2.count > 0 && entry2.count == lsmWidth * lsmHeight * 4) {
-
-            OpcodeListBuilder builder;
-            status_t err = builder.addGainMapsForMetadata(lsmWidth,
-                                                          lsmHeight,
-                                                          0,
-                                                          0,
-                                                          imageHeight,
-                                                          imageWidth,
-                                                          opcodeCfaLayout,
-                                                          entry2.data.f);
-            if (err == OK) {
-                size_t listSize = builder.getSize();
-                uint8_t opcodeListBuf[listSize];
-                err = builder.buildOpList(opcodeListBuf);
-                if (err == OK) {
-                    BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
-                            TIFF_IFD_0), env, TAG_OPCODELIST2, writer);
-                } else {
-                    ALOGE("%s: Could not build Lens shading map opcode.", __FUNCTION__);
-                    jniThrowRuntimeException(env, "failed to construct lens shading map opcode.");
-                }
-            } else {
+            err = builder.addGainMapsForMetadata(lsmWidth,
+                                                 lsmHeight,
+                                                 0,
+                                                 0,
+                                                 imageHeight,
+                                                 imageWidth,
+                                                 opcodeCfaLayout,
+                                                 entry2.data.f);
+            if (err != OK) {
                 ALOGE("%s: Could not add Lens shading map.", __FUNCTION__);
                 jniThrowRuntimeException(env, "failed to add lens shading map.");
+                return;
             }
+        }
+
+        // Set up rectilinear distortion correction
+        camera_metadata_entry entry3 =
+                results.find(ANDROID_LENS_RADIAL_DISTORTION);
+        camera_metadata_entry entry4 =
+                results.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
+
+        if (entry3.count == 6 && entry4.count == 5) {
+            float cx = entry4.data.f[/*c_x*/2];
+            float cy = entry4.data.f[/*c_y*/3];
+            err = builder.addWarpRectilinearForMetadata(entry3.data.f, imageWidth, imageHeight, cx,
+                    cy);
+            if (err != OK) {
+                ALOGE("%s: Could not add distortion correction.", __FUNCTION__);
+                jniThrowRuntimeException(env, "failed to add distortion correction.");
+                return;
+            }
+        }
+
+
+        size_t listSize = builder.getSize();
+        uint8_t opcodeListBuf[listSize];
+        err = builder.buildOpList(opcodeListBuf);
+        if (err == OK) {
+            BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
+                    TIFF_IFD_0), env, TAG_OPCODELIST2, writer);
         } else {
-            ALOGW("%s: No lens shading map found in result metadata. Image quality may be reduced.",
-                    __FUNCTION__);
+            ALOGE("%s: Could not build list of opcodes for distortion correction and lens shading"
+                    "map.", __FUNCTION__);
+            jniThrowRuntimeException(env, "failed to construct opcode list for distortion"
+                    " correction and lens shading map");
+            return;
         }
     }
 
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 1cd07d1..ac00532 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -677,13 +677,14 @@
         // constructed by java code with correct class type (device, mix etc...)
         // and reference to AudioPort instance in this client
         jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
-                                           jHandle,
-                                           0,
-                                           NULL,
-                                           NULL,
-                                           NULL,
-                                           NULL,
-                                           NULL);
+                                           jHandle, // handle
+                                           0,       // role
+                                           NULL,    // name
+                                           NULL,    // samplingRates
+                                           NULL,    // channelMasks
+                                           NULL,    // channelIndexMasks
+                                           NULL,    // formats
+                                           NULL);   // gains
         env->DeleteLocalRef(jHandle);
         if (jAudioPort == NULL) {
             return (jint)AUDIO_JAVA_ERROR;
@@ -837,11 +838,14 @@
     jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
     jintArray jSamplingRates = NULL;
     jintArray jChannelMasks = NULL;
+    jintArray jChannelIndexMasks = NULL;
     jintArray jFormats = NULL;
     jobjectArray jGains = NULL;
     jobject jHandle = NULL;
     jstring jDeviceName = NULL;
     bool useInMask;
+    size_t numPositionMasks = 0;
+    size_t numIndexMasks = 0;
 
     ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
         nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
@@ -856,23 +860,43 @@
                                (jint *)nAudioPort->sample_rates);
     }
 
-    jChannelMasks = env->NewIntArray(nAudioPort->num_channel_masks);
+    // count up how many masks are positional and indexed
+    for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
+        const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
+        if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+            numIndexMasks++;
+        } else {
+            numPositionMasks++;
+        }
+    }
+
+    jChannelMasks = env->NewIntArray(numPositionMasks);
     if (jChannelMasks == NULL) {
         jStatus = (jint)AUDIO_JAVA_ERROR;
         goto exit;
     }
+    jChannelIndexMasks = env->NewIntArray(numIndexMasks);
+    if (jChannelIndexMasks == NULL) {
+        jStatus = (jint)AUDIO_JAVA_ERROR;
+        goto exit;
+    }
     useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
 
-    jint jMask;
-    for (size_t j = 0; j < nAudioPort->num_channel_masks; j++) {
-        if (useInMask) {
-            jMask = inChannelMaskFromNative(nAudioPort->channel_masks[j]);
+    // put the masks in the output arrays
+    for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
+         maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
+        const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
+        if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+            jint jMask = audio_channel_mask_get_bits(mask);
+            env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
         } else {
-            jMask = outChannelMaskFromNative(nAudioPort->channel_masks[j]);
+            jint jMask = useInMask ? inChannelMaskFromNative(mask)
+                                   : outChannelMaskFromNative(mask);
+            env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
         }
-        env->SetIntArrayRegion(jChannelMasks, j, 1, &jMask);
     }
 
+    // formats
     jFormats = env->NewIntArray(nAudioPort->num_formats);
     if (jFormats == NULL) {
         jStatus = (jint)AUDIO_JAVA_ERROR;
@@ -883,14 +907,17 @@
         env->SetIntArrayRegion(jFormats, j, 1, &jFormat);
     }
 
+    // gains
     jGains = env->NewObjectArray(nAudioPort->num_gains,
                                           gAudioGainClass, NULL);
     if (jGains == NULL) {
         jStatus = (jint)AUDIO_JAVA_ERROR;
         goto exit;
     }
+
     for (size_t j = 0; j < nAudioPort->num_gains; j++) {
         audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
+        jint jMask;
         if (useInMask) {
             jMask = inChannelMaskFromNative(nMask);
             ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
@@ -931,7 +958,8 @@
         jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
         *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
                                      jHandle, jDeviceName,
-                                     jSamplingRates, jChannelMasks, jFormats, jGains,
+                                     jSamplingRates, jChannelMasks, jChannelIndexMasks,
+                                     jFormats, jGains,
                                      nAudioPort->ext.device.type, jAddress);
         env->DeleteLocalRef(jAddress);
     } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
@@ -939,7 +967,7 @@
         *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
                                      jHandle, nAudioPort->ext.mix.handle,
                                      nAudioPort->role, jDeviceName,
-                                     jSamplingRates, jChannelMasks,
+                                     jSamplingRates, jChannelMasks, jChannelIndexMasks,
                                      jFormats, jGains);
     } else {
         ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
@@ -1634,7 +1662,7 @@
     jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
     gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
     gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
-            "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
+            "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
     gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
                                                "Landroid/media/AudioHandle;");
     gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
@@ -1672,12 +1700,12 @@
     jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
     gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
     gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
-            "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
+            "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
 
     jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
     gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
     gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
-            "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
+            "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
 
     jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
     gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 9a80f1d..2b1067b 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -41,32 +41,8 @@
 };
 static levels_t levels;
 
-static int toLevel(const char* value)
-{
-    switch (value[0]) {
-        case 'V': return levels.verbose;
-        case 'D': return levels.debug;
-        case 'I': return levels.info;
-        case 'W': return levels.warn;
-        case 'E': return levels.error;
-        case 'A': return levels.assert;
-        case 'S': return -1; // SUPPRESS
-    }
-    return levels.info;
-}
-
 static jboolean isLoggable(const char* tag, jint level) {
-    String8 key;
-    key.append(LOG_NAMESPACE);
-    key.append(tag);
-
-    char buf[PROPERTY_VALUE_MAX];
-    if (property_get(key.string(), buf, "") <= 0) {
-        buf[0] = '\0';
-    }
-
-    int logLevel = toLevel(buf);
-    return logLevel >= 0 && level >= logLevel;
+    return __android_log_is_loggable(level, tag, ANDROID_LOG_INFO);
 }
 
 static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a434a13..65c064b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -289,6 +289,8 @@
     <protected-broadcast android:name="android.location.GPS_FIX_CHANGE" />
     <protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
 
+    <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
+
     <protected-broadcast
         android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
 
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index c0d9995..94e9c4e 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -115,4 +115,6 @@
 
     <!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
     <dimen name="immersive_mode_cling_width">380dp</dimen>
+
+    <dimen name="floating_toolbar_preferred_width">544dp</dimen>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e7811df..7272ae3 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1271,11 +1271,6 @@
          an mcc/mnc specific config.xml -->
     <string name="mobile_provisioning_url" translatable="false"></string>
 
-    <!-- This url is used as the default url when redirection is detected. Any
-         should work as all url's get redirected. But maybe overridden by
-         if needed. -->
-    <string name="mobile_redirected_provisioning_url" translatable="false">http://google.com</string>
-
     <!-- The default character set for GsmAlphabet -->
     <!-- Empty string means MBCS is not considered -->
     <string name="gsm_alphabet_default_charset" translatable="false"></string>
@@ -2196,6 +2191,9 @@
     <!-- Keyguard component -->
     <string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>
 
+    <!-- For performance and storage reasons, limit the number of fingerprints per user -->
+    <integer name="config_fingerprintMaxTemplatesPerUser">5</integer>
+
     <!-- This config is used to force VoiceInteractionService to start on certain low ram devices.
          It declares the package name of VoiceInteractionService that should be started. -->
     <string translatable="false" name="config_forceVoiceInteractionServicePackage"></string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2908cc5..fb0455d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -34,7 +34,7 @@
          to display a size in kilobytes, megabytes, or other size units.
          Some languages (like French) will want to add a space between
          the placeholders. -->
-    <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g><xliff:g id="unit" example="KB">%2$s</xliff:g></string>
+    <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g> <xliff:g id="unit" example="KB">%2$s</xliff:g></string>
 
     <!-- [CHAR_LIMIT=10] Suffix added to signify duration in days -->
     <string name="durationDays"><xliff:g id="days">%1$d</xliff:g> days</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 45e5d17..5ba57c4 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -818,7 +818,6 @@
   <java-symbol type="string" name="progress_unmounting" />
   <java-symbol type="string" name="mobile_provisioning_apn" />
   <java-symbol type="string" name="mobile_provisioning_url" />
-  <java-symbol type="string" name="mobile_redirected_provisioning_url" />
   <java-symbol type="string" name="quick_contacts_not_available" />
   <java-symbol type="string" name="reboot_to_update_package" />
   <java-symbol type="string" name="reboot_to_update_prepare" />
@@ -2125,6 +2124,9 @@
   <java-symbol type="string" name="fingerprint_error_lockout" />
   <java-symbol type="string" name="fingerprint_name_template" />
 
+  <!-- Fingerprint config -->
+  <java-symbol type="integer" name="config_fingerprintMaxTemplatesPerUser"/>
+
   <!-- From various Material changes -->
   <java-symbol type="attr" name="titleTextAppearance" />
   <java-symbol type="attr" name="subtitleTextAppearance" />
@@ -2309,5 +2311,6 @@
   <java-symbol type="string" name="ext_media_unsupported_notification_message" />
   <java-symbol type="string" name="ext_media_unsupported_notification_title" />
   <java-symbol type="plurals" name="selected_count" />
+  <java-symbol type="drawable" name="ic_dialog_alert_material" />
 
 </resources>
diff --git a/core/tests/coretests/src/android/net/NetworkTest.java b/core/tests/coretests/src/android/net/NetworkTest.java
index b0ecb049..74b6d98 100644
--- a/core/tests/coretests/src/android/net/NetworkTest.java
+++ b/core/tests/coretests/src/android/net/NetworkTest.java
@@ -16,11 +16,14 @@
 
 package android.net;
 
+import static android.test.MoreAsserts.assertNotEqual;
+
 import android.net.LocalServerSocket;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.net.Network;
 import android.test.suitebuilder.annotation.SmallTest;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -29,6 +32,7 @@
 import java.net.InetAddress;
 import java.net.Inet6Address;
 import java.net.SocketException;
+
 import junit.framework.TestCase;
 
 public class NetworkTest extends TestCase {
@@ -93,4 +97,50 @@
             fail("SocketException not thrown");
         } catch (SocketException expected) {}
     }
+
+    @SmallTest
+    public void testZeroIsObviousForDebugging() {
+        Network zero = new Network(0);
+        assertEquals(0, zero.hashCode());
+        assertEquals(0, zero.getNetworkHandle());
+        assertEquals("0", zero.toString());
+    }
+
+    @SmallTest
+    public void testGetNetworkHandle() {
+        Network one = new Network(1);
+        Network two = new Network(2);
+        Network three = new Network(3);
+
+        // None of the hashcodes are zero.
+        assertNotEqual(0, one.hashCode());
+        assertNotEqual(0, two.hashCode());
+        assertNotEqual(0, three.hashCode());
+
+        // All the hashcodes are distinct.
+        assertNotEqual(one.hashCode(), two.hashCode());
+        assertNotEqual(one.hashCode(), three.hashCode());
+        assertNotEqual(two.hashCode(), three.hashCode());
+
+        // None of the handles are zero.
+        assertNotEqual(0, one.getNetworkHandle());
+        assertNotEqual(0, two.getNetworkHandle());
+        assertNotEqual(0, three.getNetworkHandle());
+
+        // All the handles are distinct.
+        assertNotEqual(one.getNetworkHandle(), two.getNetworkHandle());
+        assertNotEqual(one.getNetworkHandle(), three.getNetworkHandle());
+        assertNotEqual(two.getNetworkHandle(), three.getNetworkHandle());
+
+        // The handles are not equal to the hashcodes.
+        assertNotEqual(one.hashCode(), one.getNetworkHandle());
+        assertNotEqual(two.hashCode(), two.getNetworkHandle());
+        assertNotEqual(three.hashCode(), three.getNetworkHandle());
+
+        // Adjust as necessary to test an implementation's specific constants.
+        // When running with runtest, "adb logcat -s TestRunner" can be useful.
+        assertEquals(4311403230L, one.getNetworkHandle());
+        assertEquals(8606370526L, two.getNetworkHandle());
+        assertEquals(12901337822L, three.getNetworkHandle());
+    }
 }
diff --git a/data/fonts/DroidSansMono.ttf b/data/fonts/DroidSansMono.ttf
index 4085cee..b7bf5b4 100644
--- a/data/fonts/DroidSansMono.ttf
+++ b/data/fonts/DroidSansMono.ttf
Binary files differ
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index 82836e2..86089e6 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -1594,7 +1594,8 @@
       "training/enterprise/app-restrictions.html",
       "https://www.youtube.com/watch?v=39NkpWkaH8M&index=2&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX",
       "samples/AppRestrictionSchema/index.html",
-      "samples/AppRestrictionEnforcer/index.html"
+      "samples/AppRestrictionEnforcer/index.html",
+      "https://www.youtube.com/watch?v=dH41OutAMNM"
     ]
   },
   "training/work/admin": {
diff --git a/docs/html/training/tv/publishing/checklist.jd b/docs/html/training/tv/publishing/checklist.jd
index 865a89b..6259721 100644
--- a/docs/html/training/tv/publishing/checklist.jd
+++ b/docs/html/training/tv/publishing/checklist.jd
@@ -67,12 +67,12 @@
 
 <li>
   Eliminate requirements for unsupported hardware in your app.
-  <p>See <a href="training/tv/start/hardware.html#declare-hardware-requirements">Declaring hardware requirements for TV</a>.</p>
+  <p>See <a href="{@docRoot}training/tv/start/hardware.html#declare-hardware-requirements">Declaring hardware requirements for TV</a>.</p>
 </li>
 
 <li>
   Ensure permissions do not imply hardware requirements
-  <p>See <a href="training/tv/start/hardware.html#hardware-permissions">Declaring permissions that imply hardware features</a>.</p>
+  <p>See <a href="{@docRoot}training/tv/start/hardware.html#hardware-permissions">Declaring permissions that imply hardware features</a>.</p>
 </li>
 
 </ol>
diff --git a/keystore/java/android/security/EcIesParameterSpec.java b/keystore/java/android/security/EcIesParameterSpec.java
deleted file mode 100644
index 1cd8784..0000000
--- a/keystore/java/android/security/EcIesParameterSpec.java
+++ /dev/null
@@ -1,272 +0,0 @@
-package android.security;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.security.spec.AlgorithmParameterSpec;
-
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-
-/**
- * {@link AlgorithmParameterSpec} for ECIES (Integrated Encryption Scheme using Elliptic Curve
- * cryptography) based on {@code ISO/IEC 18033-2}.
- *
- * <p>ECIES is a hybrid authenticated encryption scheme. Encryption is performed using an Elliptic
- * Curve (EC) public key. The resulting ciphertext can be decrypted only using the corresponding EC
- * private key. The scheme is called hybrid because the EC key is only used to securely encapsulate
- * symmetric key material. Encryption of plaintext and authentication of the corresponding
- * ciphertext is performed using symmetric cryptography.
- *
- * <p>Encryption using ECIES consists of two stages:
- * <ol>
- * <li>Key Encapsulation Mechanism (KEM) randomly generates symmetric key material and securely
- * encapsulates it in the output so that it can be extracted by the KEM when decrypting.
- * Encapsulated key material is represented in the output as an EC point.</li>
- * <li>The above symmetric key material is used by Data Encapsulation Mechanism (DEM) to encrypt the
- * provided plaintext and authenticate the ciphertext. The resulting authenticated ciphertext is
- * then output. When decrypting, the DEM first authenticates the ciphertext and, only if it
- * authenticates, decrypts the ciphertext and outputs the plaintext.</li>
- * </ol>
- *
- * <p>Details of KEM:
- * <ul>
- * <li>Only curves with cofactor of {@code 1} are supported.</li>
- * <li>{@code CheckMode}, {@code OldCofactorMode}, {@code CofactorMode}, and {@code SingleHashMode}
- * are {@code 0}.
- * <li>Point format is specified by {@link #getKemPointFormat()}.</li>
- * <li>KDF algorithm is specified by {@link #getKemKdfAlgorithm()}.</li>
- * </ul>
- *
- * <p>Details of DEM:
- * <ul>
- * <li>Only DEM1-like mechanism is supported, with its symmetric cipher (SC) specified by
- * {@link #getDemCipherTransformation()} (e.g., {@code AES/CBC/NoPadding} for standard DEM1) and
- * MAC algorithm specified by {@link #getDemMacAlgorithm()} (e.g., {@code HmacSHA1} for standard
- * DEM1).</li>
- * </ul>
- */
-public class EcIesParameterSpec implements AlgorithmParameterSpec {
-
-    /**
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-        POINT_FORMAT_UNSPECIFIED,
-        POINT_FORMAT_UNCOMPRESSED,
-        POINT_FORMAT_COMPRESSED,
-        })
-    public @interface PointFormatEnum {}
-
-    /** Unspecified EC point format. */
-    public static final int POINT_FORMAT_UNSPECIFIED = -1;
-
-    /**
-     * Uncompressed EC point format: both coordinates are stored separately.
-     *
-     * <p>The wire format is byte {@code 0x04} followed by binary representation of the {@code x}
-     * coordinate followed by binary representation of the {@code y} coordinate. See
-     * {@code ISO 18033-2} section {@code 5.4.3}.
-     */
-    public static final int POINT_FORMAT_UNCOMPRESSED = 0;
-
-    /**
-     * Compressed EC point format: only one coordinate is stored.
-     *
-     * <p>The wire format is byte {@code 0x02} or {@code 0x03} (depending on the value of the stored
-     * coordinate) followed by the binary representation of the {@code x} coordinate. See
-     * {@code ISO 18033-2} section {@code 5.4.3}.
-     */
-    public static final int POINT_FORMAT_COMPRESSED = 1;
-
-    /**
-     * Default parameter spec: compressed point format, {@code HKDFwithSHA256}, DEM uses 128-bit AES
-     * GCM.
-     */
-    public static final EcIesParameterSpec DEFAULT = new EcIesParameterSpec(
-            POINT_FORMAT_COMPRESSED,
-            "HKDFwithSHA256",
-            "AES/GCM/NoPadding",
-            128,
-            null,
-            0);
-
-    private final @PointFormatEnum int mKemPointFormat;
-    private final String mKemKdfAlgorithm;
-    private final String mDemCipherTransformation;
-    private final int mDemCipherKeySize;
-    private final String mDemMacAlgorithm;
-    private final int mDemMacKeySize;
-
-    private EcIesParameterSpec(
-            @PointFormatEnum int kemPointFormat,
-            String kemKdfAlgorithm,
-            String demCipherTransformation,
-            int demCipherKeySize,
-            String demMacAlgorithm,
-            int demMacKeySize) {
-        mKemPointFormat = kemPointFormat;
-        mKemKdfAlgorithm = kemKdfAlgorithm;
-        mDemCipherTransformation = demCipherTransformation;
-        mDemCipherKeySize = demCipherKeySize;
-        mDemMacAlgorithm = demMacAlgorithm;
-        mDemMacKeySize = demMacKeySize;
-    }
-
-    /**
-     * Returns KEM EC point wire format or {@link #POINT_FORMAT_UNSPECIFIED} if not specified.
-     */
-    public @PointFormatEnum int getKemPointFormat() {
-        return mKemPointFormat;
-    }
-
-    /**
-     * Returns KEM KDF algorithm (e.g., {@code HKDFwithSHA256} or {@code KDF1withSHA1}) or
-     * {@code null} if not specified.
-     */
-    @Nullable
-    public String getKemKdfAlgorithm() {
-        return mKemKdfAlgorithm;
-    }
-
-    /**
-     * Returns DEM {@link Cipher} transformation (e.g., {@code AES/GCM/NoPadding} or
-     * {@code AES/CBC/PKCS7Padding}) or {@code null} if not specified.
-     *
-     * @see Cipher#getInstance(String)
-     * @see #getDemCipherKeySize()
-     */
-    @Nullable
-    public String getDemCipherTransformation() {
-        return mDemCipherTransformation;
-    }
-
-    /**
-     * Returns DEM {@link Cipher} key size in bits.
-     *
-     * @see #getDemCipherTransformation()
-     */
-    public int getDemCipherKeySize() {
-        return mDemCipherKeySize;
-    }
-
-    /**
-     * Returns DEM {@link Mac} algorithm (e.g., {@code HmacSHA256} or {@code HmacSHA1}) or
-     * {@code null} if not specified.
-     *
-     * @see Mac#getInstance(String)
-     * @see #getDemMacKeySize()
-     */
-    @Nullable
-    public String getDemMacAlgorithm() {
-        return mDemMacAlgorithm;
-    }
-
-    /**
-     * Returns DEM {@link Mac} key size in bits.
-     *
-     * @see #getDemCipherTransformation()
-     */
-    public int getDemMacKeySize() {
-        return mDemMacKeySize;
-    }
-
-    /**
-     * Builder of {@link EcIesParameterSpec}.
-     */
-    public static class Builder {
-        private @PointFormatEnum int mKemPointFormat = POINT_FORMAT_UNSPECIFIED;
-        private String mKemKdfAlgorithm;
-        private String mDemCipherTransformation;
-        private int mDemCipherKeySize = 128;
-        private String mDemMacAlgorithm;
-        private int mDemMacKeySize = -1;
-
-        /**
-         * Sets KEM EC point wire format.
-         */
-        public Builder setKemPointFormat(@PointFormatEnum int pointFormat) {
-            mKemPointFormat = pointFormat;
-            return this;
-        }
-
-        /**
-         * Sets KEM KDF algorithm. For example, {@code HKDFwithSHA256}, {@code KDF2withSHA256}, or
-         * {@code KDF1withSHA1}.
-         */
-        @NonNull
-        public Builder setKemKdfAlgorithm(@Nullable String algorithm) {
-            mKemKdfAlgorithm = algorithm;
-            return this;
-        }
-
-        /**
-         * Sets DEM {@link Cipher} transformation. For example, {@code AES/GCM/NoPadding},
-         * {@code AES/CBC/PKCS7Padding} or {@code AES/CTR/NoPadding}.
-         *
-         * @see Cipher#getInstance(String)
-         */
-        @NonNull
-        public Builder setDemCipherTransformation(@Nullable String transformation) {
-            mDemCipherTransformation = transformation;
-            return this;
-        }
-
-        /**
-         * Returns DEM {@link Cipher} key size in bits.
-         *
-         * <p>The default value is {@code 128} bits.
-         *
-         * @see #setDemCipherTransformation(String)
-         */
-        @NonNull
-        public Builder setDemCipherKeySize(int sizeBits) {
-            mDemCipherKeySize = sizeBits;
-            return this;
-        }
-
-        /**
-         * Sets DEM {@link Mac} algorithm. For example, {@code HmacSHA256} or {@code HmacSHA1}.
-         *
-         * @see Mac#getInstance(String)
-         */
-        @NonNull
-        public Builder setDemMacAlgorithm(@Nullable String algorithm) {
-            mDemMacAlgorithm = algorithm;
-            return this;
-        }
-
-        /**
-         * Sets DEM {@link Mac} key size in bits.
-         *
-         * <p>By default, {@code Mac} key size is the same as the {@code Cipher} key size.
-         *
-         * @see #setDemCipherKeySize(int)
-         */
-        @NonNull
-        public Builder setDemMacKeySize(int sizeBits) {
-            mDemMacKeySize = sizeBits;
-            return this;
-        }
-
-        /**
-         * Returns a new {@link EcIesParameterSpec} based on the current state of this builder.
-         */
-        @NonNull
-        public EcIesParameterSpec build() {
-            int demMacKeySize = (mDemMacKeySize != -1) ? mDemMacKeySize : mDemCipherKeySize;
-            return new EcIesParameterSpec(
-                    mKemPointFormat,
-                    mKemKdfAlgorithm,
-                    mDemCipherTransformation,
-                    mDemCipherKeySize,
-                    mDemMacAlgorithm,
-                    demMacKeySize
-                    );
-        }
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index b93424d..2de60fd 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -624,7 +624,7 @@
             int keySizeBits,
             KeyGenParameterSpec spec) {
         // Constraints:
-        // 1. Key must be authorized for signing.
+        // 1. Key must be authorized for signing without user authentication.
         // 2. Signature digest must be one of key's authorized digests.
         // 3. For RSA keys, the digest output size must not exceed modulus size minus space needed
         //    for RSA PKCS#1 signature padding (about 29 bytes: minimum 10 bytes of padding + 15--19
@@ -636,6 +636,10 @@
             // Key not authorized for signing
             return null;
         }
+        if (spec.isUserAuthenticationRequired()) {
+            // Key not authorized for use without user authentication
+            return null;
+        }
         if (!spec.isDigestsSpecified()) {
             // Key not authorized for any digests -- can't sign
             return null;
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 47aab74..8d4bfcd 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -59,9 +59,19 @@
  * of the certificate can be customized in this spec. The self-signed certificate may be replaced at
  * a later time by a certificate signed by a Certificate Authority (CA).
  *
+ * <p>NOTE: If a private key is not authorized to sign the self-signed certificate, then the
+ * certificate will be created with an invalid signature which will not verify. Such a certificate
+ * is still useful because it provides access to the public key. To generate a valid
+ * signature for the certificate the key needs to be authorized for
+ * {@link KeyProperties#PURPOSE_SIGN}, a suitable digest or {@link KeyProperties#DIGEST_NONE}, and
+ * {@link KeyProperties#SIGNATURE_PADDING_RSA_PKCS1} or
+ * {@link KeyProperties#ENCRYPTION_PADDING_NONE}.
+ *
  * <p>NOTE: The key material of the generated symmetric and private keys is not accessible. The key
  * material of the public keys is accessible.
  *
+ * <p>Instances of this class are immutable.
+ *
  * <p><h3>Example: Asymmetric key pair</h3>
  * The following example illustrates how to generate an EC key pair in the Android KeyStore system
  * under alias {@code key1} authorized to be used only for signing using SHA-256, SHA-384,
@@ -71,11 +81,12 @@
  *         KeyProperties.KEY_ALGORITHM_EC,
  *         "AndroidKeyStore");
  * keyPairGenerator.initialize(
- *         new KeyGenParameterSpec.Builder("key1",
+ *         new KeyGenParameterSpec.Builder(
+ *                 "key1",
  *                 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
- *                 .setDigests(KeyProperties.DIGEST_SHA256
- *                         | KeyProperties.DIGEST_SHA384
- *                         | KeyProperties.DIGEST_SHA512)
+ *                 .setDigests(KeyProperties.DIGEST_SHA256,
+ *                         KeyProperties.DIGEST_SHA384,
+ *                         KeyProperties.DIGEST_SHA512)
  *                 // Only permit this key to be used if the user authenticated
  *                 // within the last five minutes.
  *                 .setUserAuthenticationRequired(true)
@@ -92,16 +103,17 @@
  *
  * <p><h3>Example: Symmetric key</h3>
  * The following example illustrates how to generate an AES key in the Android KeyStore system under
- * alias {@code key2} authorized to be used only for encryption/decryption in CTR mode.
+ * alias {@code key2} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
+ * padding.
  * <pre> {@code
  * KeyGenerator keyGenerator = KeyGenerator.getInstance(
- *         KeyProperties.KEY_ALGORITHM_HMAC_SHA256,
+ *         KeyProperties.KEY_ALGORITHM_AES,
  *         "AndroidKeyStore");
  * keyGenerator.initialize(
  *         new KeyGenParameterSpec.Builder("key2",
  *                 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- *                 .setBlockModes(KeyProperties.BLOCK_MODE_CTR)
- *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ *                 .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
+ *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
  *                 .build());
  * SecretKey key = keyGenerator.generateKey();
  *
@@ -161,10 +173,6 @@
             int userAuthenticationValidityDurationSeconds) {
         if (TextUtils.isEmpty(keyStoreAlias)) {
             throw new IllegalArgumentException("keyStoreAlias must not be empty");
-        } else if ((userAuthenticationValidityDurationSeconds < 0)
-                && (userAuthenticationValidityDurationSeconds != -1)) {
-            throw new IllegalArgumentException(
-                    "userAuthenticationValidityDurationSeconds must not be negative");
         }
 
         if (certificateSubject == null) {
@@ -189,11 +197,11 @@
         mSpec = spec;
         mCertificateSubject = certificateSubject;
         mCertificateSerialNumber = certificateSerialNumber;
-        mCertificateNotBefore = certificateNotBefore;
-        mCertificateNotAfter = certificateNotAfter;
-        mKeyValidityStart = keyValidityStart;
-        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
-        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mCertificateNotBefore = Utils.cloneIfNotNull(certificateNotBefore);
+        mCertificateNotAfter = Utils.cloneIfNotNull(certificateNotAfter);
+        mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
+        mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
+        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
         mPurposes = purposes;
         mDigests = ArrayUtils.cloneIfNotEmpty(digests);
         mEncryptionPaddings =
@@ -209,6 +217,7 @@
      * Returns the alias that will be used in the {@code java.security.KeyStore}
      * in conjunction with the {@code AndroidKeyStore}.
      */
+    @NonNull
     public String getKeystoreAlias() {
         return mKeystoreAlias;
     }
@@ -223,10 +232,10 @@
     }
 
     /**
-     * Returns the {@link AlgorithmParameterSpec} that will be used for creation
-     * of the key pair.
+     * Returns the key algorithm-specific {@link AlgorithmParameterSpec} that will be used for
+     * creation of the key or {@code null} if algorithm-specific defaults should be used.
      */
-    @NonNull
+    @Nullable
     public AlgorithmParameterSpec getAlgorithmParameterSpec() {
         return mSpec;
     }
@@ -255,7 +264,7 @@
      */
     @NonNull
     public Date getCertificateNotBefore() {
-        return mCertificateNotBefore;
+        return Utils.cloneIfNotNull(mCertificateNotBefore);
     }
 
     /**
@@ -264,7 +273,7 @@
      */
     @NonNull
     public Date getCertificateNotAfter() {
-        return mCertificateNotAfter;
+        return Utils.cloneIfNotNull(mCertificateNotAfter);
     }
 
     /**
@@ -273,7 +282,7 @@
      */
     @Nullable
     public Date getKeyValidityStart() {
-        return mKeyValidityStart;
+        return Utils.cloneIfNotNull(mKeyValidityStart);
     }
 
     /**
@@ -282,7 +291,7 @@
      */
     @Nullable
     public Date getKeyValidityForConsumptionEnd() {
-        return mKeyValidityForConsumptionEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd);
     }
 
     /**
@@ -291,7 +300,7 @@
      */
     @Nullable
     public Date getKeyValidityForOriginationEnd() {
-        return mKeyValidityForOriginationEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd);
     }
 
     /**
@@ -403,7 +412,7 @@
      * restricted.
      *
      * @return duration in seconds or {@code -1} if authentication is required for every use of the
-     *         key.
+     * key.
      *
      * @see #isUserAuthenticationRequired()
      */
@@ -439,7 +448,7 @@
          * Creates a new instance of the {@code Builder}.
          *
          * @param keystoreAlias alias of the entry in which the generated key will appear in
-         *        Android KeyStore.
+         *        Android KeyStore. Must not be empty.
          * @param purposes set of purposes (e.g., encrypt, decrypt, sign) for which the key can be
          *        used. Attempts to use the key for any other purpose will be rejected.
          *
@@ -454,6 +463,8 @@
         public Builder(@NonNull String keystoreAlias, @KeyProperties.PurposeEnum int purposes) {
             if (keystoreAlias == null) {
                 throw new NullPointerException("keystoreAlias == null");
+            } else if (keystoreAlias.isEmpty()) {
+                throw new IllegalArgumentException("keystoreAlias must not be empty");
             }
             mKeystoreAlias = keystoreAlias;
             mPurposes = purposes;
@@ -480,7 +491,11 @@
 
         /**
          * Sets the algorithm-specific key generation parameters. For example, for RSA keys this may
-         * be an instance of {@link java.security.spec.RSAKeyGenParameterSpec}.
+         * be an instance of {@link java.security.spec.RSAKeyGenParameterSpec} whereas for EC keys
+         * this may be an instance of {@link java.security.spec.ECGenParameterSpec}.
+         *
+         * <p>These key generation parameters must match other explicitly set parameters (if any),
+         * such as key size.
          */
         public Builder setAlgorithmParameterSpec(@NonNull AlgorithmParameterSpec spec) {
             if (spec == null) {
@@ -529,7 +544,7 @@
             if (date == null) {
                 throw new NullPointerException("date == null");
             }
-            mCertificateNotBefore = date;
+            mCertificateNotBefore = Utils.cloneIfNotNull(date);
             return this;
         }
 
@@ -544,7 +559,7 @@
             if (date == null) {
                 throw new NullPointerException("date == null");
             }
-            mCertificateNotAfter = date;
+            mCertificateNotAfter = Utils.cloneIfNotNull(date);
             return this;
         }
 
@@ -557,7 +572,7 @@
          */
         @NonNull
         public Builder setKeyValidityStart(Date startDate) {
-            mKeyValidityStart = startDate;
+            mKeyValidityStart = Utils.cloneIfNotNull(startDate);
             return this;
         }
 
@@ -586,7 +601,7 @@
          */
         @NonNull
         public Builder setKeyValidityForOriginationEnd(Date endDate) {
-            mKeyValidityForOriginationEnd = endDate;
+            mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -600,7 +615,7 @@
          */
         @NonNull
         public Builder setKeyValidityForConsumptionEnd(Date endDate) {
-            mKeyValidityForConsumptionEnd = endDate;
+            mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -760,14 +775,15 @@
         @NonNull
         public Builder setUserAuthenticationValidityDurationSeconds(
                 @IntRange(from = -1) int seconds) {
+            if (seconds < -1) {
+                throw new IllegalArgumentException("seconds must be -1 or larger");
+            }
             mUserAuthenticationValidityDurationSeconds = seconds;
             return this;
         }
 
         /**
          * Builds an instance of {@code KeyGenParameterSpec}.
-         *
-         * @throws IllegalArgumentException if a required field is missing
          */
         @NonNull
         public KeyGenParameterSpec build() {
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index e4f921e..03b4100 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -33,6 +33,8 @@
  * is authorized for (e.g., only in {@code CBC} mode, or signing only), whether the key should be
  * encrypted at rest, the key's and validity start and end dates.
  *
+ * <p>Instances of this class are immutable.
+ *
  * <p><h3>Example: Symmetric Key</h3>
  * The following example illustrates how to obtain a {@code KeyInfo} describing the provided Android
  * Keystore {@link SecretKey}.
@@ -102,9 +104,9 @@
         mInsideSecureHardware = insideSecureHardware;
         mOrigin = origin;
         mKeySize = keySize;
-        mKeyValidityStart = keyValidityStart;
-        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
-        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
+        mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
+        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
         mPurposes = purposes;
         mEncryptionPaddings =
                 ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
@@ -155,7 +157,7 @@
      */
     @Nullable
     public Date getKeyValidityStart() {
-        return mKeyValidityStart;
+        return Utils.cloneIfNotNull(mKeyValidityStart);
     }
 
     /**
@@ -165,7 +167,7 @@
      */
     @Nullable
     public Date getKeyValidityForConsumptionEnd() {
-        return mKeyValidityForConsumptionEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd);
     }
 
     /**
@@ -175,7 +177,7 @@
      */
     @Nullable
     public Date getKeyValidityForOriginationEnd() {
-        return mKeyValidityForOriginationEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd);
     }
 
     /**
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index 403e814..f9fe176 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -370,7 +370,7 @@
      * No encryption padding.
      *
      * <p><b>NOTE</b>: If a key is authorized to be used with no padding, then it can be used with
-     * any padding scheme.
+     * any padding scheme, both for encryption and signing.
      */
     public static final String ENCRYPTION_PADDING_NONE = "NoPadding";
 
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 432fc12..1e0611c 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -47,6 +47,8 @@
  *
  * <p>NOTE: The key material of keys stored in the Android KeyStore is not accessible.
  *
+ * <p>Instances of this class are immutable.
+ *
  * <p><h3>Example: Symmetric Key</h3>
  * The following example illustrates how to import an AES key into the Android KeyStore under alias
  * {@code key1} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
@@ -122,15 +124,9 @@
             boolean randomizedEncryptionRequired,
             boolean userAuthenticationRequired,
             int userAuthenticationValidityDurationSeconds) {
-        if ((userAuthenticationValidityDurationSeconds < 0)
-                && (userAuthenticationValidityDurationSeconds != -1)) {
-            throw new IllegalArgumentException(
-                    "userAuthenticationValidityDurationSeconds must not be negative");
-        }
-
-        mKeyValidityStart = keyValidityStart;
-        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
-        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
+        mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
+        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
         mPurposes = purposes;
         mEncryptionPaddings =
                 ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
@@ -150,7 +146,7 @@
      */
     @Nullable
     public Date getKeyValidityStart() {
-        return mKeyValidityStart;
+        return Utils.cloneIfNotNull(mKeyValidityStart);
     }
 
     /**
@@ -160,7 +156,7 @@
      */
     @Nullable
     public Date getKeyValidityForConsumptionEnd() {
-        return mKeyValidityForConsumptionEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd);
     }
 
     /**
@@ -170,7 +166,7 @@
      */
     @Nullable
     public Date getKeyValidityForOriginationEnd() {
-        return mKeyValidityForOriginationEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd);
     }
 
     /**
@@ -320,7 +316,7 @@
          */
         @NonNull
         public Builder setKeyValidityStart(Date startDate) {
-            mKeyValidityStart = startDate;
+            mKeyValidityStart = Utils.cloneIfNotNull(startDate);
             return this;
         }
 
@@ -349,7 +345,7 @@
          */
         @NonNull
         public Builder setKeyValidityForOriginationEnd(Date endDate) {
-            mKeyValidityForOriginationEnd = endDate;
+            mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -363,7 +359,7 @@
          */
         @NonNull
         public Builder setKeyValidityForConsumptionEnd(Date endDate) {
-            mKeyValidityForConsumptionEnd = endDate;
+            mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -517,6 +513,9 @@
         @NonNull
         public Builder setUserAuthenticationValidityDurationSeconds(
                 @IntRange(from = -1) int seconds) {
+            if (seconds < -1) {
+                throw new IllegalArgumentException("seconds must be -1 or larger");
+            }
             mUserAuthenticationValidityDurationSeconds = seconds;
             return this;
         }
diff --git a/keystore/java/android/security/keystore/Utils.java b/keystore/java/android/security/keystore/Utils.java
new file mode 100644
index 0000000..9bec682
--- /dev/null
+++ b/keystore/java/android/security/keystore/Utils.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import java.util.Date;
+
+/**
+ * Assorted utility methods.
+ *
+ * @hide
+ */
+abstract class Utils {
+    private Utils() {}
+
+    static Date cloneIfNotNull(Date value) {
+        return (value != null) ? (Date) value.clone() : null;
+    }
+}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index b4cbc36..fc18491 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -241,8 +241,12 @@
         animatorDirtyMask = mAnimatorManager.animate(info);
     }
 
-    bool willHaveFunctor = info.mode == TreeInfo::MODE_FULL && mStagingDisplayListData
-            ? !mStagingDisplayListData->functors.isEmpty() : !mDisplayListData->functors.isEmpty();
+    bool willHaveFunctor = false;
+    if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayListData) {
+        willHaveFunctor = !mStagingDisplayListData->functors.isEmpty();
+    } else if (mDisplayListData) {
+        willHaveFunctor = !mDisplayListData->functors.isEmpty();
+    }
     bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
             willHaveFunctor, functorsNeedLayer);
 
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 431d37e..173d349 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -173,8 +173,7 @@
      * @see AudioFormat
      */
     public @NonNull int[] getChannelIndexMasks() {
-        // TODO: implement
-        return new int[0];
+        return mPort.channelIndexMasks();
     }
 
     /**
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index c078260..aea39a3 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -37,12 +37,12 @@
     private final String mAddress;
 
     AudioDevicePort(AudioHandle handle, String deviceName,
-            int[] samplingRates, int[] channelMasks,
+            int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
             int[] formats, AudioGain[] gains, int type, String address) {
         super(handle,
              (AudioManager.isInputDevice(type) == true)  ?
                         AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK,
-             deviceName, samplingRates, channelMasks, formats, gains);
+             deviceName, samplingRates, channelMasks, channelIndexMasks, formats, gains);
         mType = type;
         mAddress = address;
     }
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index ab55c8d..ba144bf 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -31,9 +31,10 @@
     private final int mIoHandle;
 
     AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName,
-            int[] samplingRates, int[] channelMasks,
+            int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
             int[] formats, AudioGain[] gains) {
-        super(handle, role, deviceName, samplingRates, channelMasks, formats, gains);
+        super(handle, role, deviceName, samplingRates, channelMasks, channelIndexMasks,
+                formats, gains);
         mIoHandle = ioHandle;
     }
 
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 7328d7a..19bf51d 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -71,12 +71,13 @@
     private final String mName;
     private final int[] mSamplingRates;
     private final int[] mChannelMasks;
+    private final int[] mChannelIndexMasks;
     private final int[] mFormats;
     private final AudioGain[] mGains;
     private AudioPortConfig mActiveConfig;
 
     AudioPort(AudioHandle handle, int role, String name,
-            int[] samplingRates, int[] channelMasks,
+            int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
             int[] formats, AudioGain[] gains) {
 
         mHandle = handle;
@@ -84,6 +85,7 @@
         mName = name;
         mSamplingRates = samplingRates;
         mChannelMasks = channelMasks;
+        mChannelIndexMasks = channelIndexMasks;
         mFormats = formats;
         mGains = gains;
     }
@@ -133,6 +135,15 @@
     }
 
     /**
+     * Get the list of supported channel index mask configurations
+     * (e.g 0x0003 means 2 channel, 0x000F means 4 channel....)
+     * Empty array if channel index mask is not relevant for this audio port
+     */
+    public int[] channelIndexMasks() {
+        return mChannelIndexMasks;
+    }
+
+    /**
      * Get the list of supported audio format configurations
      * (e.g AudioFormat.ENCODING_PCM_16BIT)
      * Empty array if format is not relevant for this audio port
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index 72dcaa8..a68361b 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -132,7 +132,8 @@
      *
      * @param storageId the storage unit to query
      * @param format the format of the object to return, or zero for all formats
-     * @param objectHandle the parent object to query, or zero for the storage root
+     * @param objectHandle the parent object to query, -1 for the storage root,
+     *     or zero for all objects
      * @return the object handles
      */
     public int[] getObjectHandles(int storageId, int format, int objectHandle) {
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 73a723d..4143e15 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -120,13 +120,20 @@
             if (!volume.isMountedReadable()) continue;
 
             final String rootId;
-            if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
+            final String title;
+            if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
+                // We currently only support a single emulated volume mounted at
+                // a time, and it's always considered the primary
                 rootId = ROOT_ID_PRIMARY_EMULATED;
-            } else if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
-                final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
-                rootId = privateVol.getFsUuid();
+                if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
+                    title = getContext().getString(R.string.root_internal_storage);
+                } else {
+                    final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
+                    title = mStorageManager.getBestVolumeDescription(privateVol);
+                }
             } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC) {
                 rootId = volume.getFsUuid();
+                title = mStorageManager.getBestVolumeDescription(volume);
             } else {
                 // Unsupported volume; ignore
                 continue;
@@ -148,11 +155,7 @@
                 root.rootId = rootId;
                 root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
                         | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
-                if (ROOT_ID_PRIMARY_EMULATED.equals(rootId)) {
-                    root.title = getContext().getString(R.string.root_internal_storage);
-                } else {
-                    root.title = mStorageManager.getBestVolumeDescription(volume);
-                }
+                root.title = title;
                 if (volume.getType() == VolumeInfo.TYPE_PUBLIC) {
                     root.flags |= Root.FLAG_HAS_SETTINGS;
                 }
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index e1bfc43..13747ed 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -33,11 +33,23 @@
 import android.os.SystemProperties;
 import android.support.v4.content.FileProvider;
 import android.text.format.DateUtils;
+import android.util.Log;
 import android.util.Patterns;
 
 import com.google.android.collect.Lists;
+import libcore.io.Streams;
 
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 import java.util.ArrayList;
 
 /**
@@ -73,30 +85,14 @@
         final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
         final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
 
-        Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri);
-        Intent notifIntent;
-
-        // Send through warning dialog by default
-        if (getWarningState(context, STATE_SHOW) == STATE_SHOW) {
-            notifIntent = buildWarningIntent(context, sendIntent);
+        boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
+        if (!isPlainText) {
+            // Already zipped, send it right away.
+            sendBugreportNotification(context, bugreportFile, screenshotFile);
         } else {
-            notifIntent = sendIntent;
+            // Asynchronously zip the file first, then send it.
+            sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
         }
-        notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Notification.Builder builder = new Notification.Builder(context)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                .setContentTitle(context.getString(R.string.bugreport_finished_title))
-                .setTicker(context.getString(R.string.bugreport_finished_title))
-                .setContentText(context.getString(R.string.bugreport_finished_text))
-                .setContentIntent(PendingIntent.getActivity(
-                        context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
-                .setAutoCancel(true)
-                .setLocalOnly(true)
-                .setColor(context.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-
-        NotificationManager.from(context).notify(TAG, 0, builder.build());
 
         // Clean up older bugreports in background
         final PendingResult result = goAsync();
@@ -141,6 +137,88 @@
     }
 
     /**
+     * Sends a bugreport notitication.
+     */
+    private static void sendBugreportNotification(Context context, File bugreportFile,
+            File screenshotFile) {
+        // Files are kept on private storage, so turn into Uris that we can
+        // grant temporary permissions for.
+        final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
+        final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
+
+        Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri);
+        Intent notifIntent;
+
+        // Send through warning dialog by default
+        if (getWarningState(context, STATE_SHOW) == STATE_SHOW) {
+            notifIntent = buildWarningIntent(context, sendIntent);
+        } else {
+            notifIntent = sendIntent;
+        }
+        notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        final Notification.Builder builder = new Notification.Builder(context)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setContentTitle(context.getString(R.string.bugreport_finished_title))
+                .setTicker(context.getString(R.string.bugreport_finished_title))
+                .setContentText(context.getString(R.string.bugreport_finished_text))
+                .setContentIntent(PendingIntent.getActivity(
+                        context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
+                .setAutoCancel(true)
+                .setLocalOnly(true)
+                .setColor(context.getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
+
+        NotificationManager.from(context).notify(TAG, 0, builder.build());
+    }
+
+    /**
+     * Sends a zipped bugreport notification.
+     */
+    private static void sendZippedBugreportNotification(final Context context,
+            final File bugreportFile, final File screenshotFile) {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                File zippedFile = zipBugreport(bugreportFile);
+                sendBugreportNotification(context, zippedFile, screenshotFile);
+                return null;
+            }
+        }.execute();
+    }
+
+    /**
+     * Zips a bugreport file, returning the path to the new file (or to the
+     * original in case of failure).
+     */
+    private static File zipBugreport(File bugreportFile) {
+        String bugreportPath = bugreportFile.getAbsolutePath();
+        String zippedPath = bugreportPath.replace(".txt", ".zip");
+        Log.v(TAG, "zipping " + bugreportPath + " as " + zippedPath);
+        File bugreportZippedFile = new File(zippedPath);
+        try (InputStream is = new FileInputStream(bugreportFile);
+            ZipOutputStream zos = new ZipOutputStream(
+                new BufferedOutputStream(new FileOutputStream(bugreportZippedFile)))) {
+            ZipEntry entry = new ZipEntry("bugreport.txt");
+            zos.putNextEntry(entry);
+            int totalBytes = Streams.copy(is, zos);
+            Log.v(TAG, "size of original bugreport: " + totalBytes + " bytes");
+            zos.closeEntry();
+            // Delete old file;
+            boolean deleted = bugreportFile.delete();
+            if (deleted) {
+                Log.v(TAG, "deleted original bugreport (" + bugreportPath + ")");
+            } else {
+                Log.e(TAG, "could not delete original bugreport (" + bugreportPath + ")");
+            }
+            return bugreportZippedFile;
+        } catch (IOException e) {
+          Log.e(TAG, "exception zipping file " + zippedPath, e);
+          return bugreportFile;  // Return original.
+        }
+    }
+
+    /**
      * Find the best matching {@link Account} based on build properties.
      */
     private static Account findSendToAccount(Context context) {
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java b/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
index e4feb90..9839329 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
@@ -36,6 +36,8 @@
 
     private static final long DO_NOT_CACHE_RESULT = 0L;
     private static final int HTTP_CONNECTION_TIMEOUT_MILLIS = 5000;
+    private static final int HTTP_CONNECTION_BACKOFF_MILLIS = 3000;
+    private static final int HTTP_CONNECTION_RETRY = 3;
     private static final long HTTP_CONTENT_SIZE_LIMIT_IN_BYTES = 1024 * 1024;
     private static final int MAX_INCLUDE_LEVEL = 1;
     private static final String WELL_KNOWN_STATEMENT_PATH = "/.well-known/assetlinks.json";
@@ -151,9 +153,10 @@
                     && !url.getProtocol().toLowerCase().equals("https")) {
                 return Result.create(statements, DO_NOT_CACHE_RESULT);
             }
-            webContent = mUrlFetcher.getWebContentFromUrl(url,
-                    HTTP_CONTENT_SIZE_LIMIT_IN_BYTES, HTTP_CONNECTION_TIMEOUT_MILLIS);
-        } catch (IOException e) {
+            webContent = mUrlFetcher.getWebContentFromUrlWithRetry(url,
+                    HTTP_CONTENT_SIZE_LIMIT_IN_BYTES, HTTP_CONNECTION_TIMEOUT_MILLIS,
+                    HTTP_CONNECTION_BACKOFF_MILLIS, HTTP_CONNECTION_RETRY);
+        } catch (IOException | InterruptedException e) {
             return Result.create(statements, DO_NOT_CACHE_RESULT);
         }
 
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java b/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
index 225e26c..23cd832 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
@@ -49,6 +49,40 @@
     /**
      * Fetches the specified url and returns the content and ttl.
      *
+     * <p>
+     * Retry {@code retry} times if the connection failed or timed out for any reason.
+     * HTTP error code (e.g. 404/500) won't be retried.
+     *
+     * @throws IOException if it can't retrieve the content due to a network problem.
+     * @throws AssociationServiceException if the URL scheme is not http or https or the content
+     * length exceeds {code fileSizeLimit}.
+     */
+    public WebContent getWebContentFromUrlWithRetry(URL url, long fileSizeLimit,
+            int connectionTimeoutMillis, int backoffMillis, int retry)
+                    throws AssociationServiceException, IOException, InterruptedException {
+        if (retry <= 0) {
+            throw new IllegalArgumentException("retry should be a postive inetger.");
+        }
+        while (retry > 0) {
+            try {
+                return getWebContentFromUrl(url, fileSizeLimit, connectionTimeoutMillis);
+            } catch (IOException e) {
+                retry--;
+                if (retry == 0) {
+                    throw e;
+                }
+            }
+
+            Thread.sleep(backoffMillis);
+        }
+
+        // Should never reach here.
+        return null;
+    }
+
+    /**
+     * Fetches the specified url and returns the content and ttl.
+     *
      * @throws IOException if it can't retrieve the content due to a network problem.
      * @throws AssociationServiceException if the URL scheme is not http or https or the content
      * length exceeds {code fileSizeLimit}.
diff --git a/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml b/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml
new file mode 100644
index 0000000..21caab4
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="350"
+        android:propertyName="alpha"
+        android:valueFrom="1.0"
+        android:valueTo="0.3"
+        android:valueType="floatType"
+        android:interpolator="@android:interpolator/linear" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_dnd_disable_bar01_0_animation.xml b/packages/SystemUI/res/anim/ic_dnd_disable_bar01_0_animation.xml
new file mode 100644
index 0000000..a914687c
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_dnd_disable_bar01_0_animation.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="350"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.680404663086,3.53039550781 c 0.0,0.0 -0.01416015625,0.00492858886719 -0.01416015625,0.00492858886719 c 0.0,0.0 1.41400146484,-1.41400146484 1.41400146484,-1.41400146484 c 0.0,0.0 0.0151519775391,-0.00492858886719 0.0151519775391,-0.00492858886719 c 0.0,0.0 -1.41499328613,1.41400146484 -1.41499328613,1.41400146484 Z"
+        android:valueTo="M 0.680404663086,3.53039550781 c 0.0,0.0 20.0110015869,20.0110015869 20.0110015869,20.0110015869 c 0.0,0.0 1.41400146484,-1.41400146484 1.41400146484,-1.41400146484 c 0.0,0.0 -20.0100097656,-20.0110015869 -20.0100097656,-20.0110015869 c 0.0,0.0 -1.41499328613,1.41400146484 -1.41499328613,1.41400146484 Z"
+        android:valueType="pathType"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_dnd_disable_mask_1_animation.xml b/packages/SystemUI/res/anim/ic_dnd_disable_mask_1_animation.xml
new file mode 100644
index 0000000..3c60c013
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_dnd_disable_mask_1_animation.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="350"
+        android:propertyName="pathData"
+        android:valueFrom="M -9.67768859863,-9.82725524902 c 0.0,0.0 -7.8091583252,7.18409729004 -7.8091583252,7.18409729004 c 0.0,0.0 20.9320983887,20.9321136475 20.9320983887,20.9321136475 c 0.0,0.0 15.041595459,-15.0416717529 15.041595459,-15.0416717529 c 0.0,0.0 -20.5361938477,-20.536239624 -20.5361938477,-20.536239624 c 0.0,0.0 -6.20835876465,6.05171203613 -6.20835876465,6.05171203613 c 0.0,0.0 0.219390869141,0.219299316406 0.219390869141,0.219299316406 c 0.0,0.0 -1.41998291016,1.40998840332 -1.41998291016,1.40998840332 c 0.0,0.0 -0.219390869141,-0.219299316406 -0.219390869141,-0.219299316406 Z"
+        android:valueTo="M -9.67768859863,-9.82725524902 c 0.0,0.0 -7.8091583252,7.18409729004 -7.8091583252,7.18409729004 c 0.0,0.0 20.9320983887,20.9321136475 20.9320983887,20.9321136475 c 0.0,0.0 15.041595459,-15.0416717529 15.041595459,-15.0416717529 c 0.0,0.0 -20.5361938477,-20.536239624 -20.5361938477,-20.536239624 c 0.0,0.0 -6.20835876465,6.05171203613 -6.20835876465,6.05171203613 c 0.0,0.0 20.4531555176,20.4530792236 20.4531555176,20.4530792236 c 0.0,0.0 -1.41999816895,1.40995788574 -1.41999816895,1.40995788574 c 0.0,0.0 -20.4531402588,-20.4530487061 -20.4531402588,-20.4530487061 Z"
+        android:valueType="pathType"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml
new file mode 100644
index 0000000..21caab4
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="350"
+        android:propertyName="alpha"
+        android:valueFrom="1.0"
+        android:valueTo="0.3"
+        android:valueType="floatType"
+        android:interpolator="@android:interpolator/linear" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_mask_1_animation.xml b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_mask_1_animation.xml
new file mode 100644
index 0000000..8d3296e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_mask_1_animation.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="350"
+        android:propertyName="pathData"
+        android:valueFrom="M -9.67768859863,-9.82725524902 c 0.0,0.0 -7.8091583252,7.18409729004 -7.8091583252,7.18409729004 c 0.0,0.0 20.9320983887,20.9321136475 20.9320983887,20.9321136475 c 0.0,0.0 15.041595459,-15.0416717529 15.041595459,-15.0416717529 c 0.0,0.0 -20.5361938477,-20.536239624 -20.5361938477,-20.536239624 c 0.0,0.0 -6.20835876465,6.05171203613 -6.20835876465,6.05171203613 c 0.0,0.0 0.219390869141,0.219299316406 0.219390869141,0.219299316406 c 0.0,0.0 -1.41998291016,1.40998840332 -1.41998291016,1.40998840332 c 0.0,0.0 -0.219390869141,-0.219299316406 -0.219390869141,-0.219299316406 Z"
+        android:valueTo="M -9.67768859863,-9.82725524902 c 0.0,0.0 -7.8091583252,7.18409729004 -7.8091583252,7.18409729004 c 0.0,0.0 20.9320983887,20.9321136475 20.9320983887,20.9321136475 c 0.0,0.0 15.041595459,-15.0416717529 15.041595459,-15.0416717529 c 0.0,0.0 -20.5361938477,-20.536239624 -20.5361938477,-20.536239624 c 0.0,0.0 -6.20835876465,6.05171203613 -6.20835876465,6.05171203613 c 0.0,0.0 19.8804626465,19.8695220947 19.8804626465,19.8695220947 c 0.0,0.0 -1.41999816895,1.40995788574 -1.41999816895,1.40995788574 c 0.0,0.0 -19.8804473877,-19.8694915771 -19.8804473877,-19.8694915771 Z"
+        android:valueType="pathType"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_outer_ring_merged_animation.xml b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_outer_ring_merged_animation.xml
new file mode 100644
index 0000000..2626499
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_outer_ring_merged_animation.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="350"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,-10.0 c -5.5,0.0 -10.0,4.5 -10.0,10.0 c 0.0,5.5 4.5,10.0 10.0,10.0 c 5.5,0.0 10.0,-4.5 10.0,-10.0 c 0.0,-5.5 -4.5,-10.0 -10.0,-10.0 Z M 0.0,8.5 c -4.69999694824,0.0 -8.5,-3.80000305176 -8.5,-8.5 c 0.0,-4.69999694824 3.80000305176,-8.5 8.5,-8.5 c 4.69999694824,0.0 8.5,3.80000305176 8.5,8.5 c 0.0,4.69999694824 -3.80000305176,8.5 -8.5,8.5 Z M -11.3195953369,-8.46960449219 c 0.0,0.0 -0.0141754150391,0.00492858886719 -0.014175415039,0.00492858886719 c 0.0,0.0 1.41400146484,-1.41400146484 1.41400146484,-1.41400146484 c 0.0,0.0 0.0151672363281,-0.00492858886719 0.0151672363281,-0.00492858886719 c 0.0,0.0 -1.41499328613,1.41400146484 -1.41499328613,1.41400146484 Z M 3.0,1.0 c 0.0,0.0 -6.0,0.0 -6.0,0.0 c 0.0,0.0 0.0,-2.0 0.0,-2.0 c 0.0,0.0 6.0,0.0 6.0,0.0 c 0.0,0.0 0.0,2.0 0.0,2.0 Z M 0.0,-6.0 c -3.30000305176,0.0 -6.0,2.69999694824 -6.0,6.0 c 0.0,3.30000305176 2.69999694824,6.0 6.0,6.0 c 3.30000305176,0.0 6.0,-2.69999694824 6.0,-6.0 c 0.0,-3.30000305176 -2.60000610352,-6.0 -6.0,-6.0 Z"
+        android:valueTo="M 0.0,-10.0 c -5.5,0.0 -10.0,4.5 -10.0,10.0 c 0.0,5.5 4.5,10.0 10.0,10.0 c 5.5,0.0 10.0,-4.5 10.0,-10.0 c 0.0,-5.5 -4.5,-10.0 -10.0,-10.0 Z M 0.0,8.5 c -4.69999694824,0.0 -8.5,-3.80000305176 -8.5,-8.5 c 0.0,-4.69999694824 3.80000305176,-8.5 8.5,-8.5 c 4.69999694824,0.0 8.5,3.80000305176 8.5,8.5 c 0.0,4.69999694824 -3.80000305176,8.5 -8.5,8.5 Z M -11.3195953369,-8.46960449219 c 0.0,0.0 20.0109863281,20.0110015869 20.0109863281,20.0110015869 c 0.0,0.0 1.41400146484,-1.41400146484 1.41400146484,-1.41400146484 c 0.0,0.0 -20.0099945068,-20.0110015869 -20.0099945068,-20.0110015869 c 0.0,0.0 -1.41499328613,1.41400146484 -1.41499328613,1.41400146484 Z M 5.0,1.0 c 0.0,0.0 -10.0,0.0 -10.0,0.0 c 0.0,0.0 0.0,-2.0 0.0,-2.0 c 0.0,0.0 10.0,0.0 10.0,0.0 c 0.0,0.0 0.0,2.0 0.0,2.0 Z M 0.0,-10.0 c -5.52000427246,0.0 -10.0,4.47999572754 -10.0,10.0 c 0.0,5.52000427246 4.47999572754,10.0 10.0,10.0 c 5.52000427246,0.0 10.0,-4.47999572754 10.0,-10.0 c 0.0,-5.52000427246 -4.47999572754,-10.0 -10.0,-10.0 Z"
+        android:valueType="pathType"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_disable.xml b/packages/SystemUI/res/drawable/ic_dnd_disable.xml
new file mode 100644
index 0000000..ba4692a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dnd_disable.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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:name="ic_dnd_disable"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:height="24dp"
+    android:viewportHeight="24" >
+    <group
+        android:name="dnd_icon"
+        android:translateX="12"
+        android:translateY="12" >
+        <clip-path
+            android:name="mask_1"
+            android:pathData="M -9.67768859863,-9.82725524902 c 0.0,0.0 -7.8091583252,7.18409729004 -7.8091583252,7.18409729004 c 0.0,0.0 20.9320983887,20.9321136475 20.9320983887,20.9321136475 c 0.0,0.0 15.041595459,-15.0416717529 15.041595459,-15.0416717529 c 0.0,0.0 -20.5361938477,-20.536239624 -20.5361938477,-20.536239624 c 0.0,0.0 -6.20835876465,6.05171203613 -6.20835876465,6.05171203613 c 0.0,0.0 0.219390869141,0.219299316406 0.219390869141,0.219299316406 c 0.0,0.0 -1.41998291016,1.40998840332 -1.41998291016,1.40998840332 c 0.0,0.0 -0.219390869141,-0.219299316406 -0.219390869141,-0.219299316406 Z" />
+        <group
+            android:name="bar01"
+            android:translateX="-12"
+            android:translateY="-12" >
+            <path
+                android:name="bar01_0"
+                android:pathData="M 0.680404663086,3.53039550781 c 0.0,0.0 -0.01416015625,0.00492858886719 -0.01416015625,0.00492858886719 c 0.0,0.0 1.41400146484,-1.41400146484 1.41400146484,-1.41400146484 c 0.0,0.0 0.0151519775391,-0.00492858886719 0.0151519775391,-0.00492858886719 c 0.0,0.0 -1.41499328613,1.41400146484 -1.41499328613,1.41400146484 Z"
+                android:fillColor="#FFFFFFFF" />
+        </group>
+        <group
+            android:name="circle" >
+            <path
+                android:name="icon_center_merged"
+                android:pathData="M 5.0,1.0 c 0.0,0.0 -10.0,0.0 -10.0,0.0 c 0.0,0.0 0.0,-2.0 0.0,-2.0 c 0.0,0.0 10.0,0.0 10.0,0.0 c 0.0,0.0 0.0,2.0 0.0,2.0 Z M 0.0,-10.0 c -5.52000427246,0.0 -10.0,4.47999572754 -10.0,10.0 c 0.0,5.52000427246 4.47999572754,10.0 10.0,10.0 c 5.52000427246,0.0 10.0,-4.47999572754 10.0,-10.0 c 0.0,-5.52000427246 -4.47999572754,-10.0 -10.0,-10.0 Z"
+                android:fillColor="#FFFFFFFF" />
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml b/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml
new file mode 100644
index 0000000..13ed767
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<animated-vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_dnd_disable" >
+    <target
+        android:name="mask_1"
+        android:animation="@anim/ic_dnd_disable_mask_1_animation" />
+    <target
+        android:name="bar01_0"
+        android:animation="@anim/ic_dnd_disable_bar01_0_animation" />
+    <target
+        android:name="ic_dnd_disable"
+        android:animation="@anim/ic_dnd_disable_alpha_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable.xml
new file mode 100644
index 0000000..1a33255
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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:name="ic_dnd_total_silence_disable"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:height="24dp"
+    android:viewportHeight="24" >
+    <group
+        android:name="tot_silence"
+        android:translateX="12"
+        android:translateY="12" >
+        <clip-path
+            android:name="mask_1"
+            android:pathData="M -9.67768859863,-9.82725524902 c 0.0,0.0 -7.8091583252,7.18409729004 -7.8091583252,7.18409729004 c 0.0,0.0 20.9320983887,20.9321136475 20.9320983887,20.9321136475 c 0.0,0.0 15.041595459,-15.0416717529 15.041595459,-15.0416717529 c 0.0,0.0 -20.5361938477,-20.536239624 -20.5361938477,-20.536239624 c 0.0,0.0 -6.20835876465,6.05171203613 -6.20835876465,6.05171203613 c 0.0,0.0 0.219390869141,0.219299316406 0.219390869141,0.219299316406 c 0.0,0.0 -1.41998291016,1.40998840332 -1.41998291016,1.40998840332 c 0.0,0.0 -0.219390869141,-0.219299316406 -0.219390869141,-0.219299316406 Z" />
+        <group
+            android:name="icon_shape" >
+            <path
+                android:name="outer_ring_merged"
+                android:pathData="M 0.0,-10.0 c -5.5,0.0 -10.0,4.5 -10.0,10.0 c 0.0,5.5 4.5,10.0 10.0,10.0 c 5.5,0.0 10.0,-4.5 10.0,-10.0 c 0.0,-5.5 -4.5,-10.0 -10.0,-10.0 Z M 0.0,8.5 c -4.69999694824,0.0 -8.5,-3.80000305176 -8.5,-8.5 c 0.0,-4.69999694824 3.80000305176,-8.5 8.5,-8.5 c 4.69999694824,0.0 8.5,3.80000305176 8.5,8.5 c 0.0,4.69999694824 -3.80000305176,8.5 -8.5,8.5 Z M -11.3195953369,-8.46960449219 c 0.0,0.0 -0.0141754150391,0.00492858886719 -0.014175415039,0.00492858886719 c 0.0,0.0 1.41400146484,-1.41400146484 1.41400146484,-1.41400146484 c 0.0,0.0 0.0151672363281,-0.00492858886719 0.0151672363281,-0.00492858886719 c 0.0,0.0 -1.41499328613,1.41400146484 -1.41499328613,1.41400146484 Z M 3.0,1.0 c 0.0,0.0 -6.0,0.0 -6.0,0.0 c 0.0,0.0 0.0,-2.0 0.0,-2.0 c 0.0,0.0 6.0,0.0 6.0,0.0 c 0.0,0.0 0.0,2.0 0.0,2.0 Z M 0.0,-6.0 c -3.30000305176,0.0 -6.0,2.69999694824 -6.0,6.0 c 0.0,3.30000305176 2.69999694824,6.0 6.0,6.0 c 3.30000305176,0.0 6.0,-2.69999694824 6.0,-6.0 c 0.0,-3.30000305176 -2.60000610352,-6.0 -6.0,-6.0 Z"
+                android:fillColor="#FFFFFFFF" />
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml
new file mode 100644
index 0000000..c0b2d69
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+<animated-vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_dnd_total_silence_disable" >
+    <target
+        android:name="mask_1"
+        android:animation="@anim/ic_dnd_total_silence_disable_mask_1_animation" />
+    <target
+        android:name="outer_ring_merged"
+        android:animation="@anim/ic_dnd_total_silence_disable_outer_ring_merged_animation" />
+    <target
+        android:name="ic_dnd_total_silence_disable"
+        android:animation="@anim/ic_dnd_total_silence_disable_alpha_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a6313ad..37601884 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -164,7 +164,7 @@
     <dimen name="pull_span_min">25dp</dimen>
 
     <dimen name="qs_tile_height">88dp</dimen>
-    <dimen name="qs_tile_icon_size">28dp</dimen>
+    <dimen name="qs_tile_icon_size">24dp</dimen>
     <dimen name="qs_tile_text_size">12sp</dimen>
     <dimen name="qs_tile_divider_height">1dp</dimen>
     <dimen name="qs_panel_padding">16dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 1e7ee98..445ecb6 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -16,7 +16,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
@@ -28,12 +27,15 @@
 import android.view.WindowManager;
 import android.widget.ImageView;
 
-import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.AssistUtils;
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * Class to manage everything related to assist in SystemUI.
  */
@@ -55,7 +57,7 @@
     private final WindowManager mWindowManager;
     private AssistOrbContainer mView;
     private final PhoneStatusBar mBar;
-    private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
+    private final AssistUtils mAssistUtils;
 
     private ComponentName mAssistComponent;
 
@@ -92,8 +94,7 @@
         mContext = context;
         mBar = bar;
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
-                ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+        mAssistUtils = new AssistUtils(context);
 
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false,
@@ -140,11 +141,7 @@
     }
 
     public void hideAssist() {
-        try {
-            mVoiceInteractionManagerService.hideCurrentSession();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call hideCurrentSession", e);
-        }
+        mAssistUtils.hideCurrentSession();
     }
 
     private WindowManager.LayoutParams getLayoutParams() {
@@ -216,58 +213,27 @@
     }
 
     private void startVoiceInteractor() {
-        try {
-            mVoiceInteractionManagerService.showSessionForActiveService(mShowCallback);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call showSessionForActiveService", e);
-        }
+        mAssistUtils.showSessionForActiveService(mShowCallback);
     }
 
     public void launchVoiceAssistFromKeyguard() {
-        try {
-            mVoiceInteractionManagerService.launchVoiceAssistFromKeyguard();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call launchVoiceAssistFromKeyguard", e);
-        }
+        mAssistUtils.launchVoiceAssistFromKeyguard();
     }
 
     private boolean getVoiceInteractorSupportsAssistGesture() {
-        try {
-            return mVoiceInteractionManagerService != null
-                    && mVoiceInteractionManagerService.activeServiceSupportsAssist();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
-            return false;
-        }
+        return mAssistUtils.activeServiceSupportsAssistGesture();
     }
 
     public boolean canVoiceAssistBeLaunchedFromKeyguard() {
-        try {
-            return mVoiceInteractionManagerService != null
-                    && mVoiceInteractionManagerService.activeServiceSupportsLaunchFromKeyguard();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call activeServiceSupportsLaunchFromKeyguard", e);
-            return false;
-        }
+        return mAssistUtils.activeServiceSupportsLaunchFromKeyguard();
     }
 
     public ComponentName getVoiceInteractorComponentName() {
-        try {
-            return mVoiceInteractionManagerService.getActiveServiceComponentName();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
-            return null;
-        }
+        return mAssistUtils.getActiveServiceComponentName();
     }
 
     private boolean isVoiceSessionRunning() {
-        try {
-            return mVoiceInteractionManagerService != null
-                    && mVoiceInteractionManagerService.isSessionRunning();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to call isSessionRunning", e);
-            return false;
-        }
+        return mAssistUtils.isSessionRunning();
     }
 
     public void destroy() {
@@ -324,26 +290,11 @@
     }
 
     private void updateAssistInfo() {
-        final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
-                Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
-        if (setting != null) {
-            mAssistComponent = ComponentName.unflattenFromString(setting);
-            return;
-        }
+        mAssistComponent = mAssistUtils.getAssistComponentForUser(UserHandle.USER_CURRENT);
+    }
 
-        // Fallback to keep backward compatible behavior when there is no user setting.
-        if (getVoiceInteractorSupportsAssistGesture()) {
-            mAssistComponent = getVoiceInteractorComponentName();
-            return;
-        }
-
-        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
-        if (intent != null) {
-            mAssistComponent = intent.getComponent();
-            return;
-        }
-
-        mAssistComponent = null;
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("AssistManager state:");
+        pw.print("  mAssistComponent="); pw.println(mAssistComponent);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f00fed5..c06b34f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -371,7 +371,6 @@
         @Override
         public void onDeviceProvisioned() {
             sendUserPresentBroadcast();
-            updateInputRestricted();
         }
 
         @Override
@@ -947,7 +946,7 @@
      * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
      */
     public boolean isInputRestricted() {
-        return mShowing || mNeedToReshowWhenReenabled || shouldWaitForProvisioning();
+        return mShowing || mNeedToReshowWhenReenabled;
     }
 
     private void updateInputRestricted() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index c8212c2..9761cd1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -242,6 +242,9 @@
     }
 
     private void handleSetTileVisibility(View v, int visibility) {
+        if (visibility == VISIBLE && !mGridContentVisible) {
+            visibility = INVISIBLE;
+        }
         if (visibility == v.getVisibility()) return;
         v.setVisibility(visibility);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index f4d6f04..f97f519 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -38,6 +38,7 @@
 
 /** Quick settings tile: Do not disturb **/
 public class DndTile extends QSTile<QSTile.BooleanState> {
+
     private static final Intent ZEN_SETTINGS =
             new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
 
@@ -47,6 +48,14 @@
     private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
     private static final String EXTRA_VISIBLE = "visible";
 
+    private static final QSTile.Icon TOTAL_SILENCE =
+            ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
+
+    private final AnimationIcon mDisable =
+            new AnimationIcon(R.drawable.ic_dnd_disable_animation);
+    private final AnimationIcon mDisableTotalSilence =
+            new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation);
+
     private final ZenModeController mController;
     private final DndDetailAdapter mDetailAdapter;
 
@@ -89,6 +98,8 @@
 
     @Override
     public void handleClick() {
+        mDisable.setAllowAnimation(true);
+        mDisableTotalSilence.setAllowAnimation(true);
         MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
         if (mState.value) {
             mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
@@ -114,7 +125,7 @@
                         R.string.accessibility_quick_settings_dnd_priority_on);
                 break;
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
-                state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
+                state.icon = TOTAL_SILENCE;
                 state.label = mContext.getString(R.string.quick_settings_dnd_none_label);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_dnd_none_on);
@@ -126,7 +137,7 @@
                         R.string.accessibility_quick_settings_dnd_alarms_on);
                 break;
             default:
-                state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_off);
+                state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;
                 state.label = mContext.getString(R.string.quick_settings_dnd_label);
                 state.contentDescription =  mContext.getString(
                         R.string.accessibility_quick_settings_dnd_off);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index ff7b37f..9e0b08b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -114,14 +114,21 @@
             return;
         }
         ArraySet<String> blockList = StatusBarIconController.getIconBlacklist(newValue);
-        mBlockAirplane = blockList.contains(SLOT_AIRPLANE);
-        mBlockMobile = blockList.contains(SLOT_MOBILE);
-        mBlockWifi = blockList.contains(SLOT_WIFI);
-        mBlockEthernet = blockList.contains(SLOT_ETHERNET);
+        boolean blockAirplane = blockList.contains(SLOT_AIRPLANE);
+        boolean blockMobile = blockList.contains(SLOT_MOBILE);
+        boolean blockWifi = blockList.contains(SLOT_WIFI);
+        boolean blockEthernet = blockList.contains(SLOT_ETHERNET);
 
-        // Re-register to get new callbacks.
-        mNC.removeSignalCallback(SignalClusterView.this);
-        mNC.addSignalCallback(SignalClusterView.this);
+        if (blockAirplane != mBlockAirplane || blockMobile != mBlockMobile
+                || blockEthernet != mBlockEthernet || blockWifi != mBlockWifi) {
+            mBlockAirplane = blockAirplane;
+            mBlockMobile = blockMobile;
+            mBlockEthernet = blockEthernet;
+            mBlockWifi = blockWifi;
+            // Re-register to get new callbacks.
+            mNC.removeSignalCallback(this);
+            mNC.addSignalCallback(this);
+        }
     }
 
     public void setNetworkController(NetworkControllerImpl nc) {
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 a750572..5ac436a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1180,7 +1180,9 @@
         } else if (statusBarState == StatusBarState.KEYGUARD
                 || statusBarState == StatusBarState.SHADE_LOCKED) {
             mKeyguardBottomArea.animate().cancel();
-            mKeyguardBottomArea.setVisibility(View.VISIBLE);
+            if (!mDozing) {
+                mKeyguardBottomArea.setVisibility(View.VISIBLE);
+            }
             mKeyguardBottomArea.setAlpha(1f);
         } else {
             mKeyguardBottomArea.animate().cancel();
@@ -1263,7 +1265,7 @@
             setQsExpanded(true);
         } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
             setQsExpanded(false);
-            if (mLastAnnouncementWasQuickSettings && !mTracking) {
+            if (mLastAnnouncementWasQuickSettings && !mTracking && !isCollapsing()) {
                 announceForAccessibility(getKeyguardOrLockScreenString());
                 mLastAnnouncementWasQuickSettings = false;
             }
@@ -1717,7 +1719,8 @@
         float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
         mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
                 * mKeyguardStatusBarAnimateAlpha);
-        mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f ? VISIBLE : INVISIBLE);
+        mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f
+                && !mDozing ? VISIBLE : INVISIBLE);
         setQsTranslation(mQsExpansionHeight);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 33e8e59..69198ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -812,12 +812,7 @@
         signalClusterQs.setNetworkController(mNetworkController);
         final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
         if (isAPhone) {
-            mNetworkController.addEmergencyListener(new NetworkControllerImpl.EmergencyListener() {
-                @Override
-                public void setEmergencyCallsOnly(boolean emergencyOnly) {
-                    mHeader.setShowEmergencyCallsOnly(emergencyOnly);
-                }
-            });
+            mNetworkController.addEmergencyListener(mHeader);
         }
 
         mFlashlightController = new FlashlightController(mContext);
@@ -2692,6 +2687,9 @@
         if (mNextAlarmController != null) {
             mNextAlarmController.dump(fd, pw, args);
         }
+        if (mAssistManager != null) {
+            mAssistManager.dump(fd, pw, args);
+        }
         if (mSecurityController != null) {
             mSecurityController.dump(fd, pw, args);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index dfc6924..a81f06e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -45,6 +45,7 @@
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.UserInfoController;
 
@@ -54,7 +55,8 @@
  * The view to manage the header area in the expanded status bar.
  */
 public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener,
-        BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback {
+        BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback,
+        EmergencyListener {
 
     private boolean mExpanded;
     private boolean mListening;
@@ -527,7 +529,8 @@
         return true;
     }
 
-    public void setShowEmergencyCallsOnly(boolean show) {
+    @Override
+    public void setEmergencyCallsOnly(boolean show) {
         boolean changed = show != mShowEmergencyCallsOnly;
         if (changed) {
             mShowEmergencyCallsOnly = show;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 686e24c..0aa0b4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -34,6 +34,7 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
@@ -43,6 +44,7 @@
 public class MobileSignalController extends SignalController<
         MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
     private final TelephonyManager mPhone;
+    private final SubscriptionDefaults mDefaults;
     private final String mNetworkNameDefault;
     private final String mNetworkNameSeparator;
     @VisibleForTesting
@@ -67,13 +69,15 @@
     // need listener lists anymore.
     public MobileSignalController(Context context, Config config, boolean hasMobileData,
             TelephonyManager phone, CallbackHandler callbackHandler,
-            NetworkControllerImpl networkController, SubscriptionInfo info, Looper receiverLooper) {
+            NetworkControllerImpl networkController, SubscriptionInfo info,
+            SubscriptionDefaults defaults, Looper receiverLooper) {
         super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
                 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
                 networkController);
         mNetworkToIconLookup = new SparseArray<>();
         mConfig = config;
         mPhone = phone;
+        mDefaults = defaults;
         mSubscriptionInfo = info;
         mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(),
                 receiverLooper);
@@ -290,7 +294,7 @@
     }
 
     private void updateDataSim() {
-        int defaultDataSub = SubscriptionManager.getDefaultDataSubId();
+        int defaultDataSub = mDefaults.getDefaultDataSubId();
         if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
             mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index e8957f9..18b5820 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -71,6 +71,7 @@
     private final ConnectivityManager mConnectivityManager;
     private final SubscriptionManager mSubscriptionManager;
     private final boolean mHasMobileDataFeature;
+    private final SubscriptionDefaults mSubDefaults;
     private Config mConfig;
 
     // Subcontrollers.
@@ -124,7 +125,8 @@
                 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
                 new CallbackHandler(),
                 new AccessPointControllerImpl(context, bgLooper),
-                new MobileDataControllerImpl(context));
+                new MobileDataControllerImpl(context),
+                new SubscriptionDefaults());
         mReceiverHandler.post(mRegisterListeners);
     }
 
@@ -134,13 +136,15 @@
             SubscriptionManager subManager, Config config, Looper bgLooper,
             CallbackHandler callbackHandler,
             AccessPointControllerImpl accessPointController,
-            MobileDataControllerImpl mobileDataController) {
+            MobileDataControllerImpl mobileDataController,
+            SubscriptionDefaults defaultsHandler) {
         mContext = context;
         mConfig = config;
         mReceiverHandler = new Handler(bgLooper);
         mCallbackHandler = callbackHandler;
 
         mSubscriptionManager = subManager;
+        mSubDefaults = defaultsHandler;
         mConnectivityManager = connectivityManager;
         mHasMobileDataFeature =
                 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
@@ -233,7 +237,7 @@
     }
 
     private MobileSignalController getDataController() {
-        int dataSubId = SubscriptionManager.getDefaultDataSubId();
+        int dataSubId = mSubDefaults.getDefaultDataSubId();
         if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
             if (DEBUG) Log.e(TAG, "No data sim selected");
             return mDefaultSignalController;
@@ -251,17 +255,19 @@
     }
 
     public boolean isEmergencyOnly() {
-        int voiceSubId = SubscriptionManager.getDefaultVoiceSubId();
+        int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
         if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
             for (MobileSignalController mobileSignalController :
                                             mMobileSignalControllers.values()) {
-                if (!mobileSignalController.isEmergencyOnly()) {
+                if (!mobileSignalController.getState().isEmergency) {
+                    if (DEBUG) Log.d(TAG, "Found emergency " + mobileSignalController.mTag);
                     return false;
                 }
             }
         }
         if (mMobileSignalControllers.containsKey(voiceSubId)) {
-            return mMobileSignalControllers.get(voiceSubId).isEmergencyOnly();
+            if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
+            return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
         }
         if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
         // Something is wrong, better assume we can't make calls...
@@ -375,6 +381,11 @@
         if (!mListening) {
             return;
         }
+        doUpdateMobileControllers();
+    }
+
+    @VisibleForTesting
+    void doUpdateMobileControllers() {
         List<SubscriptionInfo> subscriptions = mSubscriptionManager.getActiveSubscriptionInfoList();
         if (subscriptions == null) {
             subscriptions = Collections.emptyList();
@@ -389,6 +400,7 @@
         }
         setCurrentSubscriptions(subscriptions);
         updateNoSims();
+        recalculateEmergency();
     }
 
     @VisibleForTesting
@@ -425,7 +437,7 @@
             } else {
                 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
                         mHasMobileDataFeature, mPhone, mCallbackHandler,
-                        this, subscriptions.get(i), mReceiverHandler.getLooper());
+                        this, subscriptions.get(i), mSubDefaults, mReceiverHandler.getLooper());
                 mMobileSignalControllers.put(subId, controller);
                 if (subscriptions.get(i).getSimSlotIndex() == 0) {
                     mDefaultSignalController = controller;
@@ -708,7 +720,7 @@
                 null, 0, 0, "");
         mMobileSignalControllers.put(id, new MobileSignalController(mContext,
                 mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
-                mReceiverHandler.getLooper()));
+                mSubDefaults, mReceiverHandler.getLooper()));
         return info;
     }
 
@@ -735,6 +747,16 @@
         void setEmergencyCallsOnly(boolean emergencyOnly);
     }
 
+    public static class SubscriptionDefaults {
+        public int getDefaultVoiceSubId() {
+            return SubscriptionManager.getDefaultVoiceSubId();
+        }
+
+        public int getDefaultDataSubId() {
+            return SubscriptionManager.getDefaultDataSubId();
+        }
+    }
+
     @VisibleForTesting
     static class Config {
         boolean showAtLeast3G = false;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 441bb16..30c08cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -36,6 +36,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
 
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
@@ -66,6 +67,7 @@
     protected TelephonyManager mMockTm;
     protected Config mConfig;
     protected CallbackHandler mCallbackHandler;
+    protected SubscriptionDefaults mMockSubDefaults;
 
     protected int mSubId;
 
@@ -79,6 +81,7 @@
         mMockTm = mock(TelephonyManager.class);
         mMockSm = mock(SubscriptionManager.class);
         mMockCm = mock(ConnectivityManager.class);
+        mMockSubDefaults = mock(SubscriptionDefaults.class);
         mNetCapabilities = new NetworkCapabilities();
         when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true);
         when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn(
@@ -92,25 +95,39 @@
         mCallbackHandler = mock(CallbackHandler.class);
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
-                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class));
+                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class),
+                mMockSubDefaults);
         setupNetworkController();
+
+        // Trigger blank callbacks to always get the current state (some tests don't trigger
+        // changes from default state).
+        mNetworkController.addSignalCallback(null);
+        mNetworkController.addEmergencyListener(null);
     }
 
     protected void setupNetworkController() {
         // For now just pretend to be the data sim, so we can test that too.
         mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
-        SubscriptionInfo subscription = mock(SubscriptionInfo.class);
-        List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>();
-        when(subscription.getSubscriptionId()).thenReturn(mSubId);
-        subs.add(subscription);
-        mNetworkController.setCurrentSubscriptions(subs);
+        setDefaultSubId(mSubId);
+        setSubscriptions(mSubId);
         mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
-        mMobileSignalController.getState().dataSim = true;
         mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
+    }
 
-        // Trigger blank callbacks to always get the current state (some tests don't trigger
-        // changes from default state).
-        mNetworkController.addSignalCallback(null);
+    protected void setDefaultSubId(int subId) {
+        when(mMockSubDefaults.getDefaultDataSubId()).thenReturn(subId);
+        when(mMockSubDefaults.getDefaultVoiceSubId()).thenReturn(subId);
+    }
+
+    protected void setSubscriptions(int... subIds) {
+        List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>();
+        for (int subId : subIds) {
+            SubscriptionInfo subscription = mock(SubscriptionInfo.class);
+            when(subscription.getSubscriptionId()).thenReturn(subId);
+            subs.add(subscription);
+        }
+        when(mMockSm.getActiveSubscriptionInfoList()).thenReturn(subs);
+        mNetworkController.doUpdateMobileControllers();
     }
 
     protected NetworkControllerImpl setUpNoMobileData() {
@@ -119,7 +136,7 @@
               = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                         mConfig, Looper.getMainLooper(), mCallbackHandler,
                         mock(AccessPointControllerImpl.class),
-                        mock(MobileDataControllerImpl.class));
+                        mock(MobileDataControllerImpl.class), mMockSubDefaults);
 
       setupNetworkController();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 15752e1de..e60e0a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -77,7 +77,7 @@
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
                 Mockito.mock(AccessPointControllerImpl.class),
-                Mockito.mock(MobileDataControllerImpl.class));
+                Mockito.mock(MobileDataControllerImpl.class), mMockSubDefaults);
         setupNetworkController();
 
         setupDefaultSignal();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 2df1980..168aebe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -21,7 +21,6 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
 import android.os.Looper;
-import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionInfo;
 import android.telephony.TelephonyManager;
@@ -30,6 +29,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.R;
 
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
 import java.util.ArrayList;
@@ -43,7 +43,8 @@
         // Create a new NetworkController as this is currently handled in constructor.
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
-                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class));
+                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class),
+                mMockSubDefaults);
         setupNetworkController();
 
         verifyLastMobileDataIndicators(false, 0, 0);
@@ -57,13 +58,33 @@
         verifyHasNoSims(true);
     }
 
+    public void testEmergencyOnly() {
+        setupDefaultSignal();
+        mNetworkController.recalculateEmergency();
+        verifyEmergencyOnly(false);
+
+        mMobileSignalController.getState().isEmergency = true;
+        mNetworkController.recalculateEmergency();
+        verifyEmergencyOnly(true);
+    }
+
+    public void testEmergencyOnlyNoSubscriptions() {
+        setupDefaultSignal();
+        mNetworkController.recalculateEmergency();
+        verifyEmergencyOnly(false);
+
+        setSubscriptions();
+        verifyEmergencyOnly(true);
+    }
+
     public void testNoSimlessIconWithoutMobile() {
         // Turn off mobile network support.
         Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
         // Create a new NetworkController as this is currently handled in constructor.
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
-                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class));
+                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class),
+                mMockSubDefaults);
         setupNetworkController();
 
         // No Subscriptions.
@@ -418,4 +439,11 @@
               TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */,
               DEFAULT_ICON /* typeIcon */);
     }
+
+    private void verifyEmergencyOnly(boolean isEmergencyOnly) {
+        ArgumentCaptor<Boolean> emergencyOnly = ArgumentCaptor.forClass(Boolean.class);
+        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setEmergencyCallsOnly(
+                emergencyOnly.capture());
+        assertEquals(isEmergencyOnly, (boolean) emergencyOnly.getValue());
+    }
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f645764..82399da 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -960,44 +960,6 @@
         return nai != null ? nai.network : null;
     }
 
-    /**
-     * Find the first Provisioning network.
-     *
-     * @return NetworkInfo or null if none.
-     */
-    private NetworkInfo getProvisioningNetworkInfo() {
-        enforceAccessPermission();
-
-        // Find the first Provisioning Network
-        NetworkInfo provNi = null;
-        for (NetworkInfo ni : getAllNetworkInfo()) {
-            if (ni.isConnectedToProvisioningNetwork()) {
-                provNi = ni;
-                break;
-            }
-        }
-        if (DBG) log("getProvisioningNetworkInfo: X provNi=" + provNi);
-        return provNi;
-    }
-
-    /**
-     * Find the first Provisioning network or the ActiveDefaultNetwork
-     * if there is no Provisioning network
-     *
-     * @return NetworkInfo or null if none.
-     */
-    @Override
-    public NetworkInfo getProvisioningOrActiveNetworkInfo() {
-        enforceAccessPermission();
-
-        NetworkInfo provNi = getProvisioningNetworkInfo();
-        if (provNi == null) {
-            provNi = getActiveNetworkInfo();
-        }
-        if (DBG) log("getProvisioningOrActiveNetworkInfo: X provNi=" + provNi);
-        return provNi;
-    }
-
     public NetworkInfo getActiveNetworkInfoUnfiltered() {
         enforceAccessPermission();
         final int uid = Binder.getCallingUid();
@@ -1567,14 +1529,6 @@
         }
     };
 
-    /** @hide */
-    @Override
-    public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
-        enforceConnectivityInternalPermission();
-        if (DBG) log("captivePortalCheckCompleted: ni=" + info + " captive=" + isCaptivePortal);
-//        mNetTrackers[info.getType()].captivePortalCheckCompleted(isCaptivePortal);
-    }
-
     /**
      * Setup data activity tracking for the given network.
      *
@@ -3357,7 +3311,6 @@
      * <?xml version="1.0" encoding="utf-8"?>
      *  <provisioningUrls>
      *   <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&amp;iccid=%1$s&amp;imei=%2$s</provisioningUrl>
-     *   <redirectedUrl mcc="310" mnc="4">http://www.google.com</redirectedUrl>
      *  </provisioningUrls>
      */
     private static final String PROVISIONING_URL_PATH =
@@ -3368,33 +3321,15 @@
     private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
     /** XML tag for individual url */
     private static final String TAG_PROVISIONING_URL = "provisioningUrl";
-    /** XML tag for redirected url */
-    private static final String TAG_REDIRECTED_URL = "redirectedUrl";
     /** XML attribute for mcc */
     private static final String ATTR_MCC = "mcc";
     /** XML attribute for mnc */
     private static final String ATTR_MNC = "mnc";
 
-    private static final int REDIRECTED_PROVISIONING = 1;
-    private static final int PROVISIONING = 2;
-
-    private String getProvisioningUrlBaseFromFile(int type) {
+    private String getProvisioningUrlBaseFromFile() {
         FileReader fileReader = null;
         XmlPullParser parser = null;
         Configuration config = mContext.getResources().getConfiguration();
-        String tagType;
-
-        switch (type) {
-            case PROVISIONING:
-                tagType = TAG_PROVISIONING_URL;
-                break;
-            case REDIRECTED_PROVISIONING:
-                tagType = TAG_REDIRECTED_URL;
-                break;
-            default:
-                throw new RuntimeException("getProvisioningUrlBaseFromFile: Unexpected parameter " +
-                        type);
-        }
 
         try {
             fileReader = new FileReader(mProvisioningUrlFile);
@@ -3408,7 +3343,7 @@
                 String element = parser.getName();
                 if (element == null) break;
 
-                if (element.equals(tagType)) {
+                if (element.equals(TAG_PROVISIONING_URL)) {
                     String mcc = parser.getAttributeValue(null, ATTR_MCC);
                     try {
                         if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
@@ -3443,19 +3378,9 @@
     }
 
     @Override
-    public String getMobileRedirectedProvisioningUrl() {
-        enforceConnectivityInternalPermission();
-        String url = getProvisioningUrlBaseFromFile(REDIRECTED_PROVISIONING);
-        if (TextUtils.isEmpty(url)) {
-            url = mContext.getResources().getString(R.string.mobile_redirected_provisioning_url);
-        }
-        return url;
-    }
-
-    @Override
     public String getMobileProvisioningUrl() {
         enforceConnectivityInternalPermission();
-        String url = getProvisioningUrlBaseFromFile(PROVISIONING);
+        String url = getProvisioningUrlBaseFromFile();
         if (TextUtils.isEmpty(url)) {
             url = mContext.getResources().getString(R.string.mobile_provisioning_url);
             log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index ad34b37..6eba3f6 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -95,8 +95,6 @@
 
     private static final boolean COMPRESS_TIME = false;
 
-    public static final String SERVICE_NAME = "deviceidle";
-
     private static final String ACTION_STEP_IDLE_STATE =
             "com.android.server.device_idle.STEP_IDLE_STATE";
 
@@ -636,7 +634,7 @@
             mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
         }
 
-        publishBinderService(SERVICE_NAME, new BinderService());
+        publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 744156b..3359060 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -731,6 +731,10 @@
             if (filter.getAutoVerify()) {
                 if (localVerificationLOGV || debug) {
                     Slog.v(TAG, "  Filter verified: " + isFilterVerified(filter));
+                    int authorities = filter.countDataAuthorities();
+                    for (int z = 0; z < authorities; z++) {
+                        Slog.v(TAG, "   " + filter.getDataAuthority(z).getHost());
+                    }
                 }
             }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 421ba86..667abb6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -31,7 +31,6 @@
 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -5267,7 +5266,7 @@
         }
         int callerUid = Binder.getCallingUid();
         // Only the system server can kill an application
-        if (callerUid == Process.SYSTEM_UID) {
+        if (UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) {
             // Post an aysnc message to kill the application
             Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
             msg.arg1 = appid;
@@ -10338,11 +10337,12 @@
     void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) {
         mVoiceWakeLock.setWorkSource(new WorkSource(targetUid));
         if (mRunningVoice == null || mRunningVoice.asBinder() != session.asBinder()) {
-            if (mRunningVoice == null) {
+            boolean wasRunningVoice = mRunningVoice != null;
+            mRunningVoice = session;
+            if (!wasRunningVoice) {
                 mVoiceWakeLock.acquire();
                 updateSleepIfNeededLocked();
             }
-            mRunningVoice = session;
         }
     }
 
@@ -11495,7 +11495,7 @@
             for (int i=0; i<ris.size(); i++) {
                 ActivityInfo ai = ris.get(i).activityInfo;
                 ComponentName comp = new ComponentName(ai.packageName, ai.name);
-                if (false && lastDoneReceivers.contains(comp)) {
+                if (lastDoneReceivers.contains(comp)) {
                     // We already did the pre boot receiver for this app with the current
                     // platform version, so don't do it again...
                     ris.remove(i);
@@ -18595,29 +18595,24 @@
             return;
         }
         boolean isInteraction;
-        if (!mSleeping) {
-            isInteraction = app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+        // To avoid some abuse patterns, we are going to be careful about what we consider
+        // to be an app interaction.  Being the top activity doesn't count while the display
+        // is sleeping, nor do short foreground services.
+        if (app.curProcState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+            isInteraction = true;
             app.fgInteractionTime = 0;
-        } else {
-            // If the display is off, we are going to be more restrictive about what we consider
-            // to be an app interaction.  Being the top activity doesn't count, nor do generally
-            // foreground services.
-            if (app.curProcState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
-                isInteraction = true;
-                app.fgInteractionTime = 0;
-            } else if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
-                final long now = SystemClock.elapsedRealtime();
-                if (app.fgInteractionTime == 0) {
-                    app.fgInteractionTime = now;
-                    isInteraction = false;
-                } else {
-                    isInteraction = now > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME;
-                }
+        } else if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
+            final long now = SystemClock.elapsedRealtime();
+            if (app.fgInteractionTime == 0) {
+                app.fgInteractionTime = now;
+                isInteraction = false;
             } else {
-                isInteraction = app.curProcState
-                        <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
-                app.fgInteractionTime = 0;
+                isInteraction = now > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME;
             }
+        } else {
+            isInteraction = app.curProcState
+                    <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+            app.fgInteractionTime = 0;
         }
         if (isInteraction && !app.reportedInteraction) {
             String[] packages = app.getPackageList();
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index b56e326..c973386 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1167,6 +1167,10 @@
             BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo(
                     BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED);
             if (info != null && info.isValid()) {
+                if (info.getControllerEnergyUsed() < 0 || info.getControllerIdleTimeMillis() < 0 ||
+                        info.getControllerRxTimeMillis() < 0 || info.getControllerTxTimeMillis() < 0) {
+                    Slog.wtf(TAG, "Bluetooth energy data is invalid: " + info);
+                }
                 return info;
             }
         }
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7f0be57..c52a1c1 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -33,6 +33,7 @@
 import android.os.RemoteException;
 import android.os.SELinux;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.server.SystemService;
@@ -389,12 +390,12 @@
         }
     }
 
-    public List<Fingerprint> getEnrolledFingerprints(int groupId) {
-        return mFingerprintUtils.getFingerprintsForUser(mContext, groupId);
+    public List<Fingerprint> getEnrolledFingerprints(int userId) {
+        return mFingerprintUtils.getFingerprintsForUser(mContext, userId);
     }
 
-    public boolean hasEnrolledFingerprints(int groupId) {
-        return mFingerprintUtils.getFingerprintsForUser(mContext, groupId).size() > 0;
+    public boolean hasEnrolledFingerprints(int userId) {
+        return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0;
     }
 
     boolean hasPermission(String permission) {
@@ -598,6 +599,15 @@
         public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId,
                 final IFingerprintServiceReceiver receiver, final int flags) {
             checkPermission(MANAGE_FINGERPRINT);
+            final int limit =  mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
+            final int callingUid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(callingUid);
+            final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
+            if (enrolled >= limit) {
+                Slog.w(TAG, "Too many fingerprints registered");
+                return;
+            }
             final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length);
 
             final boolean restricted = isRestricted();
@@ -689,11 +699,11 @@
         }
 
         @Override // Binder call
-        public List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName) {
+        public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
             if (!canUseFingerprint(opPackageName)) {
                 return Collections.emptyList();
             }
-            return FingerprintService.this.getEnrolledFingerprints(groupId);
+            return FingerprintService.this.getEnrolledFingerprints(userId);
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 77b800e..7999321 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -246,6 +246,8 @@
                 return handleRequestActiveSource(message);
             case Constants.MESSAGE_GET_MENU_LANGUAGE:
                 return handleGetMenuLanguage(message);
+            case Constants.MESSAGE_SET_MENU_LANGUAGE:
+                return handleSetMenuLanguage(message);
             case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS:
                 return handleGivePhysicalAddress();
             case Constants.MESSAGE_GIVE_OSD_NAME:
@@ -377,6 +379,14 @@
     }
 
     @ServiceThreadOnly
+    protected boolean handleSetMenuLanguage(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        Slog.w(TAG, "Only Playback device can handle <Set Menu Language>:" + message.toString());
+        // 'return false' will cause to reply with <Feature Abort>.
+        return false;
+    }
+
+    @ServiceThreadOnly
     protected boolean handleGiveOsdName(HdmiCecMessage message) {
         assertRunOnServiceThread();
         // Note that since this method is called after logical address allocation is done,
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 30a9b43..493471b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -26,9 +26,14 @@
 import android.provider.Settings.Global;
 import android.util.Slog;
 
+import com.android.internal.app.LocalePicker;
+import com.android.internal.app.LocalePicker.LocaleInfo;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
 /**
  * Represent a logical device of type Playback residing in Android system.
  */
@@ -306,6 +311,35 @@
         return true;  // Broadcast message.
     }
 
+    @ServiceThreadOnly
+    protected boolean handleSetMenuLanguage(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+
+        try {
+            String iso3Language = new String(message.getParams(), 0, 3, "US-ASCII");
+
+            // Don't use Locale.getAvailableLocales() since it returns a locale
+            // which is not available on Settings.
+            final List<LocaleInfo> localeInfos = LocalePicker.getAllAssetLocales(
+                    mService.getContext(), false);
+            for (LocaleInfo localeInfo : localeInfos) {
+                if (localeInfo.getLocale().getISO3Language().equals(iso3Language)) {
+                    // WARNING: CEC adopts ISO/FDIS-2 for language code, while Android requires
+                    // additional country variant to pinpoint the locale. This keeps the right
+                    // locale from being chosen. 'eng' in the CEC command, for instance,
+                    // will always be mapped to en-AU among other variants like en-US, en-GB,
+                    // an en-IN, which may not be the expected one.
+                    LocalePicker.updateLocale(localeInfo.getLocale());
+                    return true;
+                }
+            }
+            Slog.w(TAG, "Can't handle <Set Menu Language> of " + iso3Language);
+            return false;
+        } catch (UnsupportedEncodingException e) {
+            return false;
+        }
+    }
+
     @Override
     @ServiceThreadOnly
     protected void sendStandby(int deviceId) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 81ef4d5..e009455 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -338,7 +338,7 @@
         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
         mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
         mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
-                DeviceIdleController.SERVICE_NAME));
+                Context.DEVICE_IDLE_CONTROLLER));
         mTime = checkNotNull(time, "missing TrustedTime");
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
 
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index 10f1696..4af7d4e 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -51,7 +51,7 @@
 public class ValidateNotificationPeople implements NotificationSignalExtractor {
     // Using a shorter log tag since setprop has a limit of 32chars on variable name.
     private static final String TAG = "ValidateNoPeople";
-    private static final boolean INFO = true;
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);;
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final boolean ENABLE_PEOPLE_VALIDATOR = true;
@@ -100,7 +100,7 @@
                 public void onChange(boolean selfChange, Uri uri, int userId) {
                     super.onChange(selfChange, uri, userId);
                     if (DEBUG || mEvictionCount % 100 == 0) {
-                        if (INFO) Slog.i(TAG, "mEvictionCount: " + mEvictionCount);
+                        if (VERBOSE) Slog.i(TAG, "mEvictionCount: " + mEvictionCount);
                     }
                     mPeopleCache.evictAll();
                     mEvictionCount++;
@@ -113,20 +113,20 @@
 
     public RankingReconsideration process(NotificationRecord record) {
         if (!mEnabled) {
-            if (INFO) Slog.i(TAG, "disabled");
+            if (VERBOSE) Slog.i(TAG, "disabled");
             return null;
         }
         if (record == null || record.getNotification() == null) {
-            if (INFO) Slog.i(TAG, "skipping empty notification");
+            if (VERBOSE) Slog.i(TAG, "skipping empty notification");
             return null;
         }
         if (record.getUserId() == UserHandle.USER_ALL) {
-            if (INFO) Slog.i(TAG, "skipping global notification");
+            if (VERBOSE) Slog.i(TAG, "skipping global notification");
             return null;
         }
         Context context = getContextAsUser(record.getUser());
         if (context == null) {
-            if (INFO) Slog.i(TAG, "skipping notification that lacks a context");
+            if (VERBOSE) Slog.i(TAG, "skipping notification that lacks a context");
             return null;
         }
         return validatePeople(context, record);
@@ -220,7 +220,7 @@
             return null;
         }
 
-        if (INFO) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId());
+        if (VERBOSE) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId());
         final LinkedList<String> pendingLookups = new LinkedList<String>();
         for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) {
             final String handle = people[personIdx];
@@ -244,7 +244,7 @@
         affinityOut[0] = affinity;
 
         if (pendingLookups.isEmpty()) {
-            if (INFO) Slog.i(TAG, "final affinity: " + affinity);
+            if (VERBOSE) Slog.i(TAG, "final affinity: " + affinity);
             if (affinity != NONE) MetricsLogger.count(mBaseContext, "note_with_people", 1);
             return null;
         }
@@ -422,7 +422,7 @@
 
         @Override
         public void work() {
-            if (INFO) Slog.i(TAG, "Executing: validation for: " + mKey);
+            if (VERBOSE) Slog.i(TAG, "Executing: validation for: " + mKey);
             long timeStartMs = System.currentTimeMillis();
             for (final String handle: mPendingLookups) {
                 LookupResult lookupResult = null;
@@ -463,7 +463,7 @@
         public void applyChangesLocked(NotificationRecord operand) {
             float affinityBound = operand.getContactAffinity();
             operand.setContactAffinity(Math.max(mContactAffinity, affinityBound));
-            if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity());
+            if (VERBOSE) Slog.i(TAG, "final affinity: " + operand.getContactAffinity());
         }
 
         public float getContactAffinity() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6e832ed..5b7dd70 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -268,6 +268,7 @@
     static final boolean DEBUG_SETTINGS = false;
     static final boolean DEBUG_PREFERRED = false;
     static final boolean DEBUG_UPGRADE = false;
+    static final boolean DEBUG_DOMAIN_VERIFICATION = false;
     private static final boolean DEBUG_BACKUP = true;
     private static final boolean DEBUG_INSTALL = false;
     private static final boolean DEBUG_REMOVE = false;
@@ -279,7 +280,6 @@
     private static final boolean DEBUG_VERIFY = false;
     private static final boolean DEBUG_DEXOPT = false;
     private static final boolean DEBUG_ABI_SELECTION = false;
-    private static final boolean DEBUG_DOMAIN_VERIFICATION = false;
 
     private static final int RADIO_UID = Process.PHONE_UID;
     private static final int LOG_UID = Process.LOG_UID;
@@ -569,8 +569,7 @@
         }
 
         private String getDefaultScheme() {
-            // TODO: replace SCHEME_HTTP with SCHEME_HTTPS
-            return IntentFilter.SCHEME_HTTP;
+            return IntentFilter.SCHEME_HTTPS;
         }
 
         @Override
@@ -11812,50 +11811,45 @@
         final int verificationId = mIntentFilterVerificationToken++;
         int count = 0;
         final String packageName = pkg.packageName;
-        ArrayList<String> allHosts = new ArrayList<>();
+        boolean needToVerify = false;
 
         synchronized (mPackages) {
+            // If any filters need to be verified, then all need to be.
             for (PackageParser.Activity a : pkg.activities) {
                 for (ActivityIntentInfo filter : a.intents) {
-                    boolean needsFilterVerification = filter.needsVerification();
-                    if (needsFilterVerification && needsNetworkVerificationLPr(filter)) {
-                        if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
-                                "Verification needed for IntentFilter:" + filter.toString());
-                        mIntentFilterVerifier.addOneIntentFilterVerification(
-                                verifierUid, userId, verificationId, filter, packageName);
-                        count++;
-                    } else if (!needsFilterVerification) {
-                        if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
-                                "No verification needed for IntentFilter:" + filter.toString());
-                        if (hasValidDomains(filter)) {
-                            ArrayList<String> hosts = filter.getHostsList();
-                            if (hosts.size() > 0) {
-                                allHosts.addAll(hosts);
-                            } else {
-                                if (allHosts.isEmpty()) {
-                                    allHosts.add("*");
-                                }
-                            }
+                    if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
+                        if (DEBUG_DOMAIN_VERIFICATION) {
+                            Slog.d(TAG, "Intent filter needs verification, so processing all filters");
                         }
-                    } else {
-                        if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
-                                "Verification already done for IntentFilter:" + filter.toString());
+                        needToVerify = true;
+                        break;
+                    }
+                }
+            }
+            if (needToVerify) {
+                for (PackageParser.Activity a : pkg.activities) {
+                    for (ActivityIntentInfo filter : a.intents) {
+                        boolean needsFilterVerification = filter.hasWebDataURI();
+                        if (needsFilterVerification && needsNetworkVerificationLPr(filter)) {
+                            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
+                                    "Verification needed for IntentFilter:" + filter.toString());
+                            mIntentFilterVerifier.addOneIntentFilterVerification(
+                                    verifierUid, userId, verificationId, filter, packageName);
+                            count++;
+                        }
                     }
                 }
             }
         }
 
         if (count > 0) {
-            mIntentFilterVerifier.startVerifications(userId);
-            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Started " + count
+            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
                     + " IntentFilter verification" + (count > 1 ? "s" : "")
-                    +  " for userId:" + userId + "!");
+                    +  " for userId:" + userId);
+            mIntentFilterVerifier.startVerifications(userId);
         } else {
-            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
-                    "No need to start any IntentFilter verification!");
-            if (allHosts.size() > 0 && mSettings.createIntentFilterVerificationIfNeededLPw(
-                    packageName, allHosts) != null) {
-                scheduleWriteSettingsLocked();
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8f2db30..cd50946 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -27,6 +27,7 @@
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.PACKAGE_INFO_GID;
+import static com.android.server.pm.PackageManagerService.DEBUG_DOMAIN_VERIFICATION;
 
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
@@ -977,7 +978,9 @@
     IntentFilterVerificationInfo getIntentFilterVerificationLPr(String packageName) {
         PackageSetting ps = mPackages.get(packageName);
         if (ps == null) {
-            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
+            }
             return null;
         }
         return ps.getIntentFilterVerificationInfo();
@@ -988,20 +991,26 @@
             ArrayList<String> domains) {
         PackageSetting ps = mPackages.get(packageName);
         if (ps == null) {
-            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
+            }
             return null;
         }
         IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
         if (ivi == null) {
             ivi = new IntentFilterVerificationInfo(packageName, domains);
             ps.setIntentFilterVerificationInfo(ivi);
-            Slog.d(PackageManagerService.TAG,
-                    "Creating new IntentFilterVerificationInfo for packageName: " + packageName);
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.d(PackageManagerService.TAG,
+                        "Creating new IntentFilterVerificationInfo for pkg: " + packageName);
+            }
         } else {
             ivi.setDomains(domains);
-            Slog.d(PackageManagerService.TAG,
-                    "Setting domains to existing IntentFilterVerificationInfo for packageName: " +
-                            packageName + " and with domains: " + ivi.getDomainsString());
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.d(PackageManagerService.TAG,
+                        "Setting domains to existing IntentFilterVerificationInfo for pkg: " +
+                                packageName + " and with domains: " + ivi.getDomainsString());
+            }
         }
         return ivi;
     }
@@ -1009,7 +1018,9 @@
     int getIntentFilterVerificationStatusLPr(String packageName, int userId) {
         PackageSetting ps = mPackages.get(packageName);
         if (ps == null) {
-            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
+            }
             return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
         }
         int status = ps.getDomainVerificationStatusForUser(userId);
@@ -1025,14 +1036,18 @@
         // Update the status for the current package
         PackageSetting current = mPackages.get(packageName);
         if (current == null) {
-            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
+            }
             return false;
         }
         current.setDomainVerificationStatusForUser(status, userId);
 
         if (current.getIntentFilterVerificationInfo() == null) {
-            Slog.w(PackageManagerService.TAG,
-                    "No IntentFilterVerificationInfo known for name: " + packageName);
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.w(PackageManagerService.TAG,
+                        "No IntentFilterVerificationInfo known: " + packageName);
+            }
             return false;
         }
 
@@ -1080,7 +1095,9 @@
     boolean removeIntentFilterVerificationLPw(String packageName, int userId) {
         PackageSetting ps = mPackages.get(packageName);
         if (ps == null) {
-            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
+            }
             return false;
         }
         ps.clearDomainVerificationStatusForUser(userId);
@@ -1549,8 +1566,10 @@
         if (verificationInfo != null && verificationInfo.getPackageName() != null) {
             serializer.startTag(null, TAG_DOMAIN_VERIFICATION);
             verificationInfo.writeToXml(serializer);
-            Log.d(TAG, "Wrote domain verification for package: "
-                    + verificationInfo.getPackageName());
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.d(TAG, "Wrote domain verification for package: "
+                        + verificationInfo.getPackageName());
+            }
             serializer.endTag(null, TAG_DOMAIN_VERIFICATION);
         }
     }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 095b7d7..4082ff3 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -966,6 +966,7 @@
         writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
         writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
         writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS);
+        writeBoolean(serializer, restrictions, UserManager.DISALLOW_FUN);
         writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
         writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
         writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
@@ -1096,6 +1097,7 @@
         readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
         readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
         readBoolean(parser, restrictions, UserManager.DISALLOW_SMS);
+        readBoolean(parser, restrictions, UserManager.DISALLOW_FUN);
         readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
         readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
         readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ea66a04..f1f61f3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -209,6 +209,7 @@
         DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_UNMUTE_MICROPHONE);
         DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADJUST_VOLUME);
         DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_FUN);
         DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SAFE_BOOT);
     }
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 837570b..75b8278 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -196,7 +196,7 @@
 
             mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
             mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
-                    ServiceManager.getService(DeviceIdleController.SERVICE_NAME));
+                    ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
             mBatteryStats = IBatteryStats.Stub.asInterface(
                     ServiceManager.getService(BatteryStats.SERVICE_NAME));
             mDisplayManager = (DisplayManager) getContext().getSystemService(
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index b0fca95..fafe44a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -853,7 +853,38 @@
         PackageMonitor mPackageMonitor = new PackageMonitor() {
             @Override
             public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
-                return super.onHandleForceStop(intent, packages, uid, doit);
+                if (DEBUG) Slog.d(TAG, "onHandleForceStop uid=" + uid + " doit=" + doit);
+
+                int userHandle = UserHandle.getUserId(uid);
+                ComponentName curInteractor = getCurInteractor(userHandle);
+                ComponentName curRecognizer = getCurRecognizer(userHandle);
+                boolean hit = false;
+                for (String pkg : packages) {
+                    if (curInteractor != null && pkg.equals(curInteractor.getPackageName())) {
+                        hit = true;
+                        break;
+                    } else if (curRecognizer != null
+                            && pkg.equals(curRecognizer.getPackageName())) {
+                        hit = true;
+                        break;
+                    }
+                }
+                if (hit && doit) {
+                    // The user is force stopping our current interactor/recognizer.
+                    // Clear the current settings and restore default state.
+                    synchronized (VoiceInteractionManagerService.this) {
+                        mSoundTriggerHelper.stopAllRecognitions();
+                        if (mImpl != null) {
+                            mImpl.shutdownLocked();
+                            mImpl = null;
+                        }
+                        setCurInteractor(null, userHandle);
+                        setCurRecognizer(null, userHandle);
+                        initForUser(userHandle);
+                        switchImplementationIfNeededLocked(true);
+                    }
+                }
+                return hit;
             }
 
             @Override
@@ -865,51 +896,53 @@
                 int userHandle = getChangingUserId();
                 if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle);
 
-                ComponentName curInteractor = getCurInteractor(userHandle);
-                ComponentName curRecognizer = getCurRecognizer(userHandle);
-                if (curRecognizer == null) {
-                    // Could a new recognizer appear when we don't have one pre-installed?
-                    if (anyPackagesAppearing()) {
-                        curRecognizer = findAvailRecognizer(null, userHandle);
-                        if (curRecognizer != null) {
-                            setCurRecognizer(curRecognizer, userHandle);
+                synchronized (VoiceInteractionManagerService.this) {
+                    ComponentName curInteractor = getCurInteractor(userHandle);
+                    ComponentName curRecognizer = getCurRecognizer(userHandle);
+                    if (curRecognizer == null) {
+                        // Could a new recognizer appear when we don't have one pre-installed?
+                        if (anyPackagesAppearing()) {
+                            curRecognizer = findAvailRecognizer(null, userHandle);
+                            if (curRecognizer != null) {
+                                setCurRecognizer(curRecognizer, userHandle);
+                            }
                         }
-                    }
-                    return;
-                }
-
-                if (curInteractor != null) {
-                    int change = isPackageDisappearing(curInteractor.getPackageName());
-                    if (change == PACKAGE_PERMANENT_CHANGE) {
-                        // The currently set interactor is permanently gone; fall back to
-                        // the default config.
-                        setCurInteractor(null, userHandle);
-                        setCurRecognizer(null, userHandle);
-                        initForUser(userHandle);
                         return;
                     }
 
-                    change = isPackageAppearing(curInteractor.getPackageName());
-                    if (change != PACKAGE_UNCHANGED) {
-                        // If current interactor is now appearing, for any reason, then
-                        // restart our connection with it.
-                        if (mImpl != null && curInteractor.getPackageName().equals(
-                                mImpl.mComponent.getPackageName())) {
-                            switchImplementationIfNeededLocked(true);
+                    if (curInteractor != null) {
+                        int change = isPackageDisappearing(curInteractor.getPackageName());
+                        if (change == PACKAGE_PERMANENT_CHANGE) {
+                            // The currently set interactor is permanently gone; fall back to
+                            // the default config.
+                            setCurInteractor(null, userHandle);
+                            setCurRecognizer(null, userHandle);
+                            initForUser(userHandle);
+                            return;
                         }
+
+                        change = isPackageAppearing(curInteractor.getPackageName());
+                        if (change != PACKAGE_UNCHANGED) {
+                            // If current interactor is now appearing, for any reason, then
+                            // restart our connection with it.
+                            if (mImpl != null && curInteractor.getPackageName().equals(
+                                    mImpl.mComponent.getPackageName())) {
+                                switchImplementationIfNeededLocked(true);
+                            }
+                        }
+                        return;
                     }
-                    return;
-                }
 
-                // There is no interactor, so just deal with a simple recognizer.
-                int change = isPackageDisappearing(curRecognizer.getPackageName());
-                if (change == PACKAGE_PERMANENT_CHANGE
-                        || change == PACKAGE_TEMPORARY_CHANGE) {
-                    setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle);
+                    // There is no interactor, so just deal with a simple recognizer.
+                    int change = isPackageDisappearing(curRecognizer.getPackageName());
+                    if (change == PACKAGE_PERMANENT_CHANGE
+                            || change == PACKAGE_TEMPORARY_CHANGE) {
+                        setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle);
 
-                } else if (isPackageModified(curRecognizer.getPackageName())) {
-                    setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(),
-                            userHandle), userHandle);
+                    } else if (isPackageModified(curRecognizer.getPackageName())) {
+                        setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(),
+                                userHandle), userHandle);
+                    }
                 }
             }
         };
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 368e137..0cd8c19 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -124,6 +124,16 @@
             "android.telecom.action.CHANGE_DEFAULT_DIALER";
 
     /**
+     * Broadcast intent action indicating that the current default dialer has changed.
+     * The string extra {@link #EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME} will contain the
+     * name of the package that the default dialer was changed to.
+     *
+     * @see #EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME
+     */
+    public static final String ACTION_DEFAULT_DIALER_CHANGED =
+            "android.telecom.action.DEFAULT_DIALER_CHANGED";
+
+    /**
      * Extra value used to provide the package name for {@link #ACTION_CHANGE_DEFAULT_DIALER}.
      */
     public static final String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME =
@@ -774,6 +784,31 @@
     }
 
     /**
+     * Used to set the default dialer package.
+     *
+     * @param packageName to set the default dialer to..
+     *
+     * @result {@code true} if the default dialer was successfully changed, {@code false} if
+     *         the specified package does not correspond to an installed dialer, or is already
+     *         the default dialer.
+     *
+     * Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     * Requires permission: {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
+     *
+     * @hide
+     */
+    public boolean setDefaultDialer(String packageName) {
+        try {
+            if (isServiceConnected()) {
+                return getTelecomService().setDefaultDialer(packageName);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException attempting to set the default dialer.", e);
+        }
+        return false;
+    }
+
+    /**
      * Used to determine the dialer package that is preloaded on the system partition.
      *
      * @return package name for the system dialer package or null if no system dialer is preloaded.
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index da0c547..bcfee30 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -84,7 +84,7 @@
      * from config.xml under apps/Contacts.
      */
     public static final String
-            KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "key_enable_dialer_vibration_bool";
+            KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_vibration_bool";
 
     /** Flag indicating if dtmf tone type is enabled */
     public static final String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
@@ -185,6 +185,13 @@
      */
     public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
 
+    /**
+     * Flag specifying whether WFC over IMS should be available for carrier: independent of
+     * carrier provisioning. If false: hard disabled. If true: then depends on carrier
+     * provisioning, availability etc.
+     */
+    public static final String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+
     /** Flag specifying whether VoLTE availability is based on provisioning. */
     public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
 
@@ -200,6 +207,13 @@
      */
     public static final String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
 
+    /**
+     * The default sim call manager to use when the default dialer doesn't implement one. A sim call
+     * manager can control and route outgoing and incoming phone calls, even if they're placed
+     * using another connection service (PSTN, for example).
+     */
+    public static final String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
+
     /* The following 3 fields are related to carrier visual voicemail. */
 
     /**
@@ -232,6 +246,34 @@
      */
     public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
 
+    /**
+     * Flag specifying whether an additional (client initiated) intent needs to be sent on System
+     * update
+     * @hide
+     */
+    public static final String KEY_CI_ACTION_ON_SYS_UPDATE_BOOL = "ci_action_on_sys_update_bool";
+
+    /**
+     * Intent to be sent for the additional action on System update
+     * @hide
+     */
+    public static final String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING =
+            "ci_action_on_sys_update_intent_string";
+
+    /**
+     * Extra to be included in the intent sent for additional action on System update
+     * @hide
+     */
+    public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING =
+            "ci_action_on_sys_update_extra_string";
+
+    /**
+     * Value of extra included in intent sent for additional action on System update
+     * @hide
+     */
+    public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING =
+            "ci_action_on_sys_update_extra_val_string";
+
     // These variables are used by the MMS service and exposed through another API, {@link
     // SmsManager}. The variable names and string values are copied from there.
     public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -278,6 +320,7 @@
         sDefaults.putBoolean(KEY_AUTO_RETRY_ENABLED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_SETTINGS_ENABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_AVAILABLE_BOOL, false);
+        sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
         sDefaults.putBoolean(KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL, false);
@@ -300,10 +343,15 @@
         sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
         sDefaults.putBoolean(KEY_WORLD_PHONE_BOOL, false);
         sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0);
+        sDefaults.putString(KEY_DEFAULT_SIM_CALL_MANAGER_STRING, "");
         sDefaults.putString(KEY_VVM_DESTINATION_NUMBER_STRING, "");
         sDefaults.putInt(KEY_VVM_PORT_NUMBER_INT, 0);
         sDefaults.putString(KEY_VVM_TYPE_STRING, "");
         sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
+        sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
+        sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");
+        sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
+        sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING, "");
 
         // MMS defaults
         sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1cc275d..8291a30 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -667,7 +667,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getDeviceSvnUsingSubId(subId[0]);
+            return info.getDeviceSvnUsingSubId(subId[0], mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -744,7 +744,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getImeiForSubscriber(subId[0]);
+            return info.getImeiForSubscriber(subId[0], mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -773,7 +773,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            String nai = info.getNaiForSubscriber(subId[0]);
+            String nai = info.getNaiForSubscriber(subId[0], mContext.getOpPackageName());
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Rlog.v(TAG, "Nai = " + nai);
             }
@@ -1856,7 +1856,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getIccSerialNumberForSubscriber(subId);
+            return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -1938,7 +1938,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getSubscriberIdForSubscriber(subId);
+            return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -1959,7 +1959,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getGroupIdLevel1();
+            return info.getGroupIdLevel1(mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -1983,7 +1983,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getGroupIdLevel1ForSubscriber(subId);
+            return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2029,7 +2029,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getLine1NumberForSubscriber(subId);
+            return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2122,7 +2122,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getLine1AlphaTagForSubscriber(subId);
+            return info.getLine1AlphaTagForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2178,7 +2178,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getMsisdnForSubscriber(subId);
+            return info.getMsisdnForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2211,7 +2211,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getVoiceMailNumberForSubscriber(subId);
+            return info.getVoiceMailNumberForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2350,7 +2350,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getVoiceMailAlphaTagForSubscriber(subId);
+            return info.getVoiceMailAlphaTagForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index c91a59c..ed85392 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -25,12 +25,12 @@
     /**
      * Retrieves the unique device ID, e.g., IMEI for GSM phones.
      */
-    String getDeviceId();
+    String getDeviceId(String callingPackage);
 
      /**
      * Retrieves the unique Network Access ID
      */
-    String getNaiForSubscriber(int subId);
+    String getNaiForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the unique device ID of a phone for the device, e.g., IMEI
@@ -41,91 +41,91 @@
     /**
      * Retrieves the IMEI.
      */
-    String getImeiForSubscriber(int subId);
+    String getImeiForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the software version number for the device, e.g., IMEI/SV
      * for GSM phones.
      */
-    String getDeviceSvn();
+    String getDeviceSvn(String callingPackage);
 
     /**
      * Retrieves the software version number of a subId for the device, e.g., IMEI/SV
      * for GSM phones.
      */
-    String getDeviceSvnUsingSubId(int subId);
+    String getDeviceSvnUsingSubId(int subId, String callingPackage);
 
     /**
      * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
      */
-    String getSubscriberId();
+    String getSubscriberId(String callingPackage);
 
     /**
      * Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones.
      */
-    String getSubscriberIdForSubscriber(int subId);
+    String getSubscriberIdForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the Group Identifier Level1 for GSM phones.
      */
-    String getGroupIdLevel1();
+    String getGroupIdLevel1(String callingPackage);
 
     /**
      * Retrieves the Group Identifier Level1 for GSM phones of a subId.
      */
-    String getGroupIdLevel1ForSubscriber(int subId);
+    String getGroupIdLevel1ForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the serial number of the ICC, if applicable.
      */
-    String getIccSerialNumber();
+    String getIccSerialNumber(String callingPackage);
 
     /**
      * Retrieves the serial number of a given subId.
      */
-    String getIccSerialNumberForSubscriber(int subId);
+    String getIccSerialNumberForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the phone number string for line 1.
      */
-    String getLine1Number();
+    String getLine1Number(String callingPackage);
 
     /**
      * Retrieves the phone number string for line 1 of a subcription.
      */
-    String getLine1NumberForSubscriber(int subId);
+    String getLine1NumberForSubscriber(int subId, String callingPackage);
 
 
     /**
      * Retrieves the alpha identifier for line 1.
      */
-    String getLine1AlphaTag();
+    String getLine1AlphaTag(String callingPackage);
 
     /**
      * Retrieves the alpha identifier for line 1 of a subId.
      */
-    String getLine1AlphaTagForSubscriber(int subId);
+    String getLine1AlphaTagForSubscriber(int subId, String callingPackage);
 
 
     /**
      * Retrieves MSISDN Number.
      */
-    String getMsisdn();
+    String getMsisdn(String callingPackage);
 
     /**
      * Retrieves the Msisdn of a subId.
      */
-    String getMsisdnForSubscriber(int subId);
+    String getMsisdnForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the voice mail number.
      */
-    String getVoiceMailNumber();
+    String getVoiceMailNumber(String callingPackage);
 
     /**
      * Retrieves the voice mail number of a given subId.
      */
-    String getVoiceMailNumberForSubscriber(int subId);
+    String getVoiceMailNumberForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the complete voice mail number.
@@ -140,13 +140,13 @@
     /**
      * Retrieves the alpha identifier associated with the voice mail number.
      */
-    String getVoiceMailAlphaTag();
+    String getVoiceMailAlphaTag(String callingPackage);
 
     /**
      * Retrieves the alpha identifier associated with the voice mail number
      * of a subId.
      */
-    String getVoiceMailAlphaTagForSubscriber(int subId);
+    String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage);
 
     /**
      * Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 94cbabf..2f0bf39 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -32,15 +32,18 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.graphics.BitmapFactory;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.graphics.Bitmap;
+import android.provider.Settings;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -60,6 +63,7 @@
     static final String KEY_CONFIGURATION = "configuration";
 
     ActivityManager mAm;
+    PowerManager mPower;
     AlarmManager mAlarm;
     Configuration mOverrideConfig;
     int mSecondUser;
@@ -158,8 +162,9 @@
 
         Log.i(TAG, "Referrer: " + getReferrer());
 
-        mAm = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
-        mAlarm = (AlarmManager)getSystemService(ALARM_SERVICE);
+        mAm = getSystemService(ActivityManager.class);
+        mPower = getSystemService(PowerManager.class);
+        mAlarm = getSystemService(AlarmManager.class);
         if (savedInstanceState != null) {
             mOverrideConfig = savedInstanceState.getParcelable(KEY_CONFIGURATION);
             if (mOverrideConfig != null) {
@@ -445,7 +450,7 @@
                 new MenuItem.OnMenuItemClickListener() {
             @Override public boolean onMenuItemClick(MenuItem item) {
                 Intent intent = new Intent(Intent.ACTION_MAIN);
-                intent.putExtra("gulp", new int[1024*1024]);
+                intent.putExtra("gulp", new int[1024 * 1024]);
                 startActivity(intent);
                 return true;
             }
@@ -457,6 +462,17 @@
                 return true;
             }
         });
+        menu.add("Ignore battery optimizations").setOnMenuItemClickListener(
+                new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
+                if (!mPower.isIgnoringBatteryOptimizations(getPackageName())) {
+                    intent.setData(Uri.fromParts("package", getPackageName(), null));
+                }
+                startActivity(intent);
+                return true;
+            }
+        });
         return true;
     }
 
diff --git a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
index 0f73342..035317e 100644
--- a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
+++ b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
@@ -39,22 +39,22 @@
     /**
      * @hide
      */
-    public int mControllerTxTimeMs;
+    public long mControllerTxTimeMs;
 
     /**
      * @hide
      */
-    public int mControllerRxTimeMs;
+    public long mControllerRxTimeMs;
 
     /**
      * @hide
      */
-    public int mControllerIdleTimeMs;
+    public long mControllerIdleTimeMs;
 
     /**
      * @hide
      */
-    public int mControllerEnergyUsed;
+    public long mControllerEnergyUsed;
 
     public static final int STACK_STATE_INVALID = 0;
     public static final int STACK_STATE_STATE_ACTIVE = 1;
@@ -62,7 +62,7 @@
     public static final int STACK_STATE_STATE_IDLE = 3;
 
     public WifiActivityEnergyInfo(long timestamp, int stackState,
-                                  int txTime, int rxTime, int idleTime, int energyUsed) {
+                                  long txTime, long rxTime, long idleTime, long energyUsed) {
         mTimestamp = timestamp;
         mStackState = stackState;
         mControllerTxTimeMs = txTime;
@@ -88,10 +88,10 @@
         public WifiActivityEnergyInfo createFromParcel(Parcel in) {
             long timestamp = in.readLong();
             int stackState = in.readInt();
-            int txTime = in.readInt();
-            int rxTime = in.readInt();
-            int idleTime = in.readInt();
-            int energyUsed = in.readInt();
+            long txTime = in.readLong();
+            long rxTime = in.readLong();
+            long idleTime = in.readLong();
+            long energyUsed = in.readLong();
             return new WifiActivityEnergyInfo(timestamp, stackState,
                     txTime, rxTime, idleTime, energyUsed);
         }
@@ -103,10 +103,10 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(mTimestamp);
         out.writeInt(mStackState);
-        out.writeInt(mControllerTxTimeMs);
-        out.writeInt(mControllerRxTimeMs);
-        out.writeInt(mControllerIdleTimeMs);
-        out.writeInt(mControllerEnergyUsed);
+        out.writeLong(mControllerTxTimeMs);
+        out.writeLong(mControllerRxTimeMs);
+        out.writeLong(mControllerIdleTimeMs);
+        out.writeLong(mControllerEnergyUsed);
     }
 
     public int describeContents() {
@@ -123,30 +123,29 @@
     /**
      * @return tx time in ms
      */
-    public int getControllerTxTimeMillis() {
-        return (int)mControllerTxTimeMs;
+    public long getControllerTxTimeMillis() {
+        return mControllerTxTimeMs;
     }
 
     /**
      * @return rx time in ms
      */
-    public int getControllerRxTimeMillis() {
-        return (int)mControllerRxTimeMs;
+    public long getControllerRxTimeMillis() {
+        return mControllerRxTimeMs;
     }
 
     /**
      * @return idle time in ms
      */
-    public int getControllerIdleTimeMillis() {
-        return (int)mControllerIdleTimeMs;
+    public long getControllerIdleTimeMillis() {
+        return mControllerIdleTimeMs;
     }
 
-
     /**
      * product of current(mA), voltage(V) and time(ms)
      * @return energy used
      */
-    public int getControllerEnergyUsed() {
+    public long getControllerEnergyUsed() {
         return mControllerEnergyUsed;
     }
     /**
@@ -160,8 +159,8 @@
      * @return if the record is valid
      */
     public boolean isValid() {
-        return ((getControllerTxTimeMillis() !=0) ||
-                (getControllerRxTimeMillis() !=0) ||
-                (getControllerIdleTimeMillis() !=0));
+        return ((mControllerTxTimeMs !=0) ||
+                (mControllerRxTimeMs !=0) ||
+                (mControllerIdleTimeMs !=0));
     }
 }