Merge "Fix user switcher ripple emanation point" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index d3b8724..80c4dc8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7160,6 +7160,7 @@
   public static final class ScanSettings.Builder {
     ctor public ScanSettings.Builder();
     method public android.bluetooth.le.ScanSettings build();
+    method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
     method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
     method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
     method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
@@ -30323,6 +30324,7 @@
     method public android.net.Uri getSubscriptionAddress();
     method public java.util.List<java.lang.String> getSupportedUriSchemes();
     method public boolean hasCapabilities(int);
+    method public boolean isEnabled();
     method public boolean supportsUriScheme(java.lang.String);
     method public android.telecom.PhoneAccount.Builder toBuilder();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 1dc5325..6c4f278 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -32509,6 +32509,7 @@
     method public android.net.Uri getSubscriptionAddress();
     method public java.util.List<java.lang.String> getSupportedUriSchemes();
     method public boolean hasCapabilities(int);
+    method public boolean isEnabled();
     method public boolean supportsUriScheme(java.lang.String);
     method public android.telecom.PhoneAccount.Builder toBuilder();
     method public void writeToParcel(android.os.Parcel, int);
@@ -32650,6 +32651,7 @@
     method public void cancelMissedCallsNotification();
     method public deprecated void clearAccounts();
     method public void clearPhoneAccounts();
+    method public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean);
     method public boolean endCall();
     method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getAllPhoneAccountHandles();
@@ -32665,7 +32667,6 @@
     method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
-    method public java.util.List<android.telecom.PhoneAccountHandle> getRegisteredConnectionManagers();
     method public android.telecom.PhoneAccountHandle getSimCallManager();
     method public java.lang.String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
     method public boolean handleMmi(java.lang.String);
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 4eeb577..d616624 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -249,9 +249,7 @@
          *
          * @param callbackType The callback type flags for the scan.
          * @throws IllegalArgumentException If the {@code callbackType} is invalid.
-         * @hide
          */
-        @SystemApi
         public Builder setCallbackType(int callbackType) {
 
             if (!isValidCallbackType(callbackType)) {
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 9046e81..7f4a76c 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -67,8 +67,6 @@
     private final TaskSingleDrainer mIdleDrainer;
     /** Drain state transitions from BUSY -> IDLE */
     private final TaskSingleDrainer mAbortDrainer;
-    /** Drain the UNCONFIGURED state transition */
-    private final TaskSingleDrainer mUnconfigureDrainer;
 
     /** This session is closed; all further calls will throw ISE */
     private boolean mClosed = false;
@@ -121,8 +119,6 @@
                 /*name*/"idle");
         mAbortDrainer = new TaskSingleDrainer(mDeviceHandler, new AbortDrainListener(),
                 /*name*/"abort");
-        mUnconfigureDrainer = new TaskSingleDrainer(mDeviceHandler, new UnconfigureDrainListener(),
-                /*name*/"unconf");
 
         // CameraDevice should call configureOutputs and have it finish before constructing us
 
@@ -572,26 +568,6 @@
             @Override
             public void onUnconfigured(CameraDevice camera) {
                 if (VERBOSE) Log.v(TAG, mIdString + "onUnconfigured");
-                synchronized (session) {
-                    // Ignore #onUnconfigured before #close is called.
-                    //
-                    // Normally, this is reached when this session is closed and no immediate other
-                    // activity happens for the camera, in which case the camera is configured to
-                    // null streams by this session and the UnconfigureDrainer task is started.
-                    // However, we can also end up here if
-                    //
-                    // 1) Session is closed
-                    // 2) New session is created before this session finishes closing, setting
-                    //    mSkipUnconfigure and therefore this session does not configure null or
-                    //    start the UnconfigureDrainer task.
-                    // 3) And then the new session fails to be created, so onUnconfigured fires
-                    //    _anyway_.
-                    // In this second case, need to not finish a task that was never started, so
-                    // guard with mSkipUnconfigure
-                    if (mClosed && mConfigureSuccess && !mSkipUnconfigure) {
-                        mUnconfigureDrainer.taskFinished();
-                    }
-                }
             }
 
             @Override
@@ -656,6 +632,19 @@
              * then the drain immediately finishes.
              */
             if (VERBOSE) Log.v(TAG, mIdString + "onSequenceDrained");
+
+
+            // Fire session close as soon as all sequences are complete.
+            // We may still need to unconfigure the device, but a new session might be created
+            // past this point, and notifications would then stop to this instance.
+            mStateCallback.onClosed(CameraCaptureSessionImpl.this);
+
+            // Fast path: A new capture session has replaced this one; don't wait for abort/idle
+            // as we won't get state updates any more anyway.
+            if (mSkipUnconfigure) {
+                return;
+            }
+
             mAbortDrainer.beginDrain();
         }
     }
@@ -673,6 +662,12 @@
                  *
                  * If the camera is already "IDLE", then the drain immediately finishes.
                  */
+
+                // Fast path: A new capture session has replaced this one; don't wait for idle
+                // as we won't get state updates any more anyway.
+                if (mSkipUnconfigure) {
+                    return;
+                }
                 mIdleDrainer.beginDrain();
             }
         }
@@ -691,7 +686,7 @@
                  * The device is now IDLE, and has settled. It will not transition to
                  * ACTIVE or BUSY again by itself.
                  *
-                 * It's now safe to unconfigure the outputs and after it's done invoke #onClosed.
+                 * It's now safe to unconfigure the outputs.
                  *
                  * This operation is idempotent; a session will not be closed twice.
                  */
@@ -699,45 +694,31 @@
                         Log.v(TAG, mIdString + "Session drain complete, skip unconfigure: " +
                                 mSkipUnconfigure);
 
-                    // Fast path: A new capture session has replaced this one; don't unconfigure.
+                    // Fast path: A new capture session has replaced this one; don't wait for idle
+                    // as we won't get state updates any more anyway.
                     if (mSkipUnconfigure) {
-                        mStateCallback.onClosed(CameraCaptureSessionImpl.this);
                         return;
                     }
 
-                    // Slow path: #close was called explicitly on this session; unconfigure first
-                    mUnconfigureDrainer.taskStarted();
-
+                    // Final slow path: unconfigure the camera, no session has replaced us and
+                    // everything is idle.
                     try {
                         // begin transition to unconfigured
                         mDeviceImpl.configureStreamsChecked(null, null);
                     } catch (CameraAccessException e) {
                         // OK: do not throw checked exceptions.
-                        Log.e(TAG, mIdString + "Exception while configuring outputs: ", e);
+                        Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);
 
                         // TODO: call onError instead of onClosed if this happens
                     } catch (IllegalStateException e) {
-                        // Camera is already closed, so go straight to the close callback
+                        // Camera is already closed, so nothing left to do
                         if (VERBOSE) Log.v(TAG, mIdString +
                                 "Camera was already closed or busy, skipping unconfigure");
-                        mUnconfigureDrainer.taskFinished();
                     }
 
-                    mUnconfigureDrainer.beginDrain();
                 }
             }
         }
     }
 
-    private class UnconfigureDrainListener implements TaskDrainer.DrainListener {
-        @Override
-
-        public void onDrained() {
-            if (VERBOSE) Log.v(TAG, mIdString + "onUnconfigureDrained");
-            synchronized (CameraCaptureSessionImpl.this) {
-                // The device has finished unconfiguring. It's now fully closed.
-                mStateCallback.onClosed(CameraCaptureSessionImpl.this);
-            }
-        }
-    }
 }
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 9623695..04e54aa 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -50,6 +50,8 @@
     public final int flags;
     public long size;
     public String label;
+    /** Hacky; don't rely on this count */
+    public int volumeCount;
 
     public DiskInfo(String id, int flags) {
         this.id = Preconditions.checkNotNull(id);
@@ -61,6 +63,7 @@
         flags = parcel.readInt();
         size = parcel.readLong();
         label = parcel.readString();
+        volumeCount = parcel.readInt();
     }
 
     public @NonNull String getId() {
@@ -181,5 +184,6 @@
         parcel.writeInt(this.flags);
         parcel.writeLong(size);
         parcel.writeString(label);
+        parcel.writeInt(volumeCount);
     }
 }
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/docs/html/preview/images/bugs.png b/docs/html/preview/images/bugs.png
deleted file mode 100644
index 46adf05..0000000
--- a/docs/html/preview/images/bugs.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/preview/images/dev-prev.png b/docs/html/preview/images/dev-prev.png
deleted file mode 100644
index eae6ede..0000000
--- a/docs/html/preview/images/dev-prev.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/preview/images/m-preview-timeline.png b/docs/html/preview/images/m-preview-timeline.png
index a065c21..bda0b46 100644
--- a/docs/html/preview/images/m-preview-timeline.png
+++ b/docs/html/preview/images/m-preview-timeline.png
Binary files differ
diff --git a/docs/html/preview/images/updates.png b/docs/html/preview/images/updates.png
deleted file mode 100644
index f165c5a..0000000
--- a/docs/html/preview/images/updates.png
+++ /dev/null
Binary files differ
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 4526839..0f1be6b 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -724,6 +725,26 @@
                 return USAGE_UNKNOWN;
         }
     }
+    /**
+     * @hide
+     * CANDIDATE FOR PUBLIC (or at least SYSTEM) API
+     * Returns the stream type matching the given attributes for volume control.
+     * Use this method to derive the stream type needed to configure the volume
+     * control slider in an {@link Activity} with {@link Activity#setVolumeControlStream(int)}.
+     * <BR>Do not use this method to set the stream type on an audio player object
+     * (e.g. {@link AudioTrack}, {@link MediaPlayer}), use <code>AudioAttributes</code> instead.
+     * @param aa non-null AudioAttributes.
+     * @return a valid stream type for <code>Activity</code> or stream volume control that matches
+     *     the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
+     *     match. Note that <code>USE_DEFAULT_STREAM_TYPE</code> is not a valid value
+     *     for {@link AudioManager#setStreamVolume(int, int, int)}.
+     */
+    public static int getVolumeControlStream(@NonNull AudioAttributes aa) {
+        if (aa == null) {
+            throw new IllegalArgumentException("Invalid null audio attributes");
+        }
+        return toVolumeStreamType(true /*fromGetVolumeControlStream*/, aa);
+    }
 
     /**
      * @hide
@@ -732,13 +753,19 @@
      * @param aa non-null AudioAttributes.
      * @return a valid stream type for volume control that matches the attributes.
      */
-    public static int toLegacyStreamType(AudioAttributes aa) {
+    public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
+        return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
+    }
+
+    private static int toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa) {
         // flags to stream type mapping
         if ((aa.getFlags() & FLAG_AUDIBILITY_ENFORCED) == FLAG_AUDIBILITY_ENFORCED) {
-            return AudioSystem.STREAM_SYSTEM_ENFORCED;
+            return fromGetVolumeControlStream ?
+                    AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
         }
         if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
-            return AudioSystem.STREAM_BLUETOOTH_SCO;
+            return fromGetVolumeControlStream ?
+                    AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
         }
 
         // usage to stream type mapping
@@ -753,7 +780,8 @@
             case USAGE_VOICE_COMMUNICATION:
                 return AudioSystem.STREAM_VOICE_CALL;
             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
-                return AudioSystem.STREAM_DTMF;
+                return fromGetVolumeControlStream ?
+                        AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_DTMF;
             case USAGE_ALARM:
                 return AudioSystem.STREAM_ALARM;
             case USAGE_NOTIFICATION_RINGTONE:
@@ -765,8 +793,15 @@
             case USAGE_NOTIFICATION_EVENT:
                 return AudioSystem.STREAM_NOTIFICATION;
             case USAGE_UNKNOWN:
+                return fromGetVolumeControlStream ?
+                        AudioManager.USE_DEFAULT_STREAM_TYPE : AudioSystem.STREAM_MUSIC;
             default:
-                return AudioSystem.STREAM_MUSIC;
+                if (fromGetVolumeControlStream) {
+                    throw new IllegalArgumentException("Unknown usage value " + aa.getUsage() +
+                            " in audio attributes");
+                } else {
+                    return AudioSystem.STREAM_MUSIC;
+                }
         }
     }
 
diff --git a/packages/DocumentsUI/res/layout/fragment_pick.xml b/packages/DocumentsUI/res/layout/fragment_pick.xml
index 87dc4f8..40d4eb5 100644
--- a/packages/DocumentsUI/res/layout/fragment_pick.xml
+++ b/packages/DocumentsUI/res/layout/fragment_pick.xml
@@ -19,13 +19,13 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:baselineAligned="false"
-    android:gravity="center_vertical"
+    android:gravity="end"
+    android:paddingEnd="8dp"
     android:minHeight="?android:attr/listPreferredItemHeightSmall">
     <Button
         android:id="@android:id/button2"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_weight="1"
         android:text="@android:string/cancel"
         android:visibility="gone"
         style="?android:attr/buttonBarNegativeButtonStyle" />
@@ -33,7 +33,5 @@
         android:id="@android:id/button1"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:textAllCaps="false"
         style="?android:attr/buttonBarPositiveButtonStyle" />
 </LinearLayout>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 5281087..9794273 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -44,8 +44,6 @@
     <string name="menu_share">Share</string>
     <!-- Menu item title that deletes the selected documents [CHAR LIMIT=24] -->
     <string name="menu_delete">Delete</string>
-    <!-- Menu item title that selects the current directory [CHAR LIMIT=48] -->
-    <string name="menu_select">Select \"<xliff:g id="directory" example="My Directory">^1</xliff:g>\"</string>
     <!-- Menu item title that selects all documents in the current directory [CHAR LIMIT=24] -->
     <string name="menu_select_all">Select All</string>
     <!-- Menu item title that copies the selected documents [CHAR LIMIT=24] -->
@@ -65,7 +63,9 @@
     <!-- Menu item that hides the sizes of displayed files [CHAR LIMIT=24] -->
     <string name="menu_file_size_hide">Hide file size</string>
 
-    <!-- Button label that copies files to the current directory [CHAR LIMIT=48] -->
+    <!-- Button label that select the current directory [CHAR LIMIT=24] -->
+    <string name="button_select">Select</string>
+    <!-- Button label that copies files to the current directory [CHAR LIMIT=24] -->
     <string name="button_copy">Copy</string>
 
     <!-- Action mode title summarizing the number of documents selected [CHAR LIMIT=32] -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index cded717..8482438 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -571,9 +571,7 @@
             mState.action == ACTION_OPEN_COPY_DESTINATION) {
             final PickFragment pick = PickFragment.get(fm);
             if (pick != null) {
-                final CharSequence displayName = (mState.stack.size() <= 1) ? root.title
-                        : cwd.displayName;
-                pick.setPickTarget(mState.action, cwd, displayName);
+                pick.setPickTarget(mState.action, cwd);
             }
         }
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
index e899379..d9b8568 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -38,15 +38,19 @@
 public class PickFragment extends Fragment {
     public static final String TAG = "PickFragment";
 
+    private int mAction;
     private DocumentInfo mPickTarget;
-
     private View mContainer;
     private Button mPick;
     private Button mCancel;
 
     public static void show(FragmentManager fm) {
-        final PickFragment fragment = new PickFragment();
+        // Fragment can be restored by FragmentManager automatically.
+        if (get(fm) != null) {
+            return;
+        }
 
+        final PickFragment fragment = new PickFragment();
         final FragmentTransaction ft = fm.beginTransaction();
         ft.replace(R.id.container_save, fragment, TAG);
         ft.commitAllowingStateLoss();
@@ -67,8 +71,7 @@
         mCancel = (Button) mContainer.findViewById(android.R.id.button2);
         mCancel.setOnClickListener(mCancelListener);
 
-        setPickTarget(0, null, null);
-
+        updateView();
         return mContainer;
     }
 
@@ -92,32 +95,38 @@
     /**
      * @param action Which action defined in BaseActivity.State is the picker shown for.
      */
-    public void setPickTarget(int action,
-                              DocumentInfo pickTarget,
-                              CharSequence displayName) {
-        if (mContainer != null) {
-            if (pickTarget != null) {
-                final Locale locale = getResources().getConfiguration().locale;
-                switch (action) {
-                    case BaseActivity.State.ACTION_OPEN_TREE:
-                        final String raw = getString(R.string.menu_select).toUpperCase(locale);
-                        mPick.setText(TextUtils.expandTemplate(raw, displayName));
-                        mCancel.setVisibility(View.GONE);
-                        break;
-                    case BaseActivity.State.ACTION_OPEN_COPY_DESTINATION:
-                        mPick.setText(getString(R.string.button_copy).toUpperCase(locale));
-                        mCancel.setVisibility(View.VISIBLE);
-                        break;
-                    default:
-                        throw new IllegalArgumentException("Illegal action for PickFragment.");
-                }
-            }
-            if (pickTarget != null && pickTarget.isCreateSupported()) {
-                mContainer.setVisibility(View.VISIBLE);
-            } else {
-                mContainer.setVisibility(View.GONE);
-            }
-        }
+    public void setPickTarget(int action, DocumentInfo pickTarget) {
+        mAction = action;
         mPickTarget = pickTarget;
+        if (mContainer != null) {
+            updateView();
+        }
+    }
+
+    /**
+     * Applies the state of fragment to the view components.
+     */
+    private void updateView() {
+        switch (mAction) {
+            case BaseActivity.State.ACTION_OPEN_TREE:
+                mPick.setText(R.string.button_select);
+                mCancel.setVisibility(View.GONE);
+                break;
+            case BaseActivity.State.ACTION_OPEN_COPY_DESTINATION:
+                mPick.setText(R.string.button_copy);
+                mCancel.setVisibility(View.VISIBLE);
+                break;
+            default:
+                mContainer.setVisibility(View.GONE);
+                return;
+        }
+
+        if (mPickTarget != null && (
+                mAction == BaseActivity.State.ACTION_OPEN_TREE ||
+                mPickTarget.isCreateSupported())) {
+            mContainer.setVisibility(View.VISIBLE);
+        } else {
+            mContainer.setVisibility(View.GONE);
+        }
     }
 }
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 9ef9211..c10be7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -117,6 +117,7 @@
      * intercepted yet.
      */
     private boolean mIntercepting;
+    private boolean mPanelExpanded;
     private boolean mQsExpanded;
     private boolean mQsExpandedWhenExpandingStarted;
     private boolean mQsFullyExpanded;
@@ -1496,13 +1497,22 @@
         updateHeader();
         updateUnlockIcon();
         updateNotificationTranslucency();
-        mHeadsUpManager.setIsExpanded(!isFullyCollapsed());
+        updatePanelExpanded();
         mNotificationStackScroller.setShadeExpanded(!isFullyCollapsed());
         if (DEBUG) {
             invalidate();
         }
     }
 
+    private void updatePanelExpanded() {
+        boolean isExpanded = !isFullyCollapsed();
+        if (mPanelExpanded != isExpanded) {
+            mHeadsUpManager.setIsExpanded(isExpanded);
+            mStatusBar.setPanelExpanded(isExpanded);
+            mPanelExpanded = isExpanded;
+        }
+    }
+
     /**
      * @return a temporary override of {@link #mQsMaxExpansionHeight}, which is needed when
      *         collapsing QS / the panel when QS was scrolled
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 1361038..9fe591e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1967,6 +1967,10 @@
         return !mUnlockMethodCache.isCurrentlyInsecure();
     }
 
+    public void setPanelExpanded(boolean isExpanded) {
+        mStatusBarWindowManager.setPanelExpanded(isExpanded);
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -2027,7 +2031,7 @@
 
         // Expand the window to encompass the full screen in anticipation of the drag.
         // This is only possible to do atomically because the status bar is at the top of the screen!
-        mStatusBarWindowManager.setStatusBarExpanded(true);
+        mStatusBarWindowManager.setPanelVisible(true);
         mStatusBarView.setFocusable(false);
 
         visibilityChanged(true);
@@ -2156,7 +2160,7 @@
         visibilityChanged(false);
 
         // Shrink the window to the size of the status bar only
-        mStatusBarWindowManager.setStatusBarExpanded(false);
+        mStatusBarWindowManager.setPanelVisible(false);
         mStatusBarWindowManager.setForceStatusBarVisible(false);
         mStatusBarView.setFocusable(true);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 422d868..4f1c652 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -114,12 +114,12 @@
     }
 
     private void applyFocusableFlag(State state) {
+        boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
         if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput
-                && state.bouncerShowing
-                || BaseStatusBar.ENABLE_REMOTE_INPUT && state.statusBarExpanded) {
+                && state.bouncerShowing || BaseStatusBar.ENABLE_REMOTE_INPUT && panelFocusable) {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) {
+        } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         } else {
@@ -130,7 +130,7 @@
 
     private void applyHeight(State state) {
         boolean expanded = !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
-                || state.statusBarExpanded || state.keyguardFadingAway || state.bouncerShowing
+                || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
                 || state.headsUpShowing);
         if (expanded) {
             mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
@@ -213,9 +213,9 @@
         apply(mCurrentState);
     }
 
-    public void setStatusBarExpanded(boolean expanded) {
-        mCurrentState.statusBarExpanded = expanded;
-        mCurrentState.statusBarFocusable = expanded;
+    public void setPanelVisible(boolean visible) {
+        mCurrentState.panelVisible = visible;
+        mCurrentState.statusBarFocusable = visible;
         apply(mCurrentState);
     }
 
@@ -267,11 +267,17 @@
         apply(mCurrentState);
     }
 
+    public void setPanelExpanded(boolean isExpanded) {
+        mCurrentState.panelExpanded = isExpanded;
+        apply(mCurrentState);
+    }
+
     private static class State {
         boolean keyguardShowing;
         boolean keyguardOccluded;
         boolean keyguardNeedsInput;
-        boolean statusBarExpanded;
+        boolean panelVisible;
+        boolean panelExpanded;
         boolean statusBarFocusable;
         boolean bouncerShowing;
         boolean keyguardFadingAway;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 23813d1..ad21555 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -148,6 +148,11 @@
                 android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
 
         // Kick current state into place
+        final List<DiskInfo> disks = mStorageManager.getDisks();
+        for (DiskInfo disk : disks) {
+            onDiskScannedInternal(disk, disk.volumeCount);
+        }
+
         final List<VolumeInfo> vols = mStorageManager.getVolumes();
         for (VolumeInfo vol : vols) {
             onVolumeStateChangedInternal(vol);
@@ -194,7 +199,7 @@
     }
 
     private void onDiskScannedInternal(DiskInfo disk, int volumeCount) {
-        if (volumeCount == 0) {
+        if (volumeCount == 0 && disk.size > 0) {
             // No supported volumes found, give user option to format
             final CharSequence title = mContext.getString(
                     R.string.ext_media_unmountable_notification_title, disk.getDescription());
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 6c1023c..01cc2ca 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1725,28 +1725,68 @@
                 // At package-changed we only care about looking at new transport states
                 if (changed) {
                     try {
+                        String[] components =
+                                intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+
                         if (MORE_DEBUG) {
                             Slog.i(TAG, "Package " + pkgName + " changed; rechecking");
+                            for (int i = 0; i < components.length; i++) {
+                                Slog.i(TAG, "   * " + components[i]);
+                            }
                         }
-                        // unbind existing possibly-stale connections to that package's transports
+
+                        // In general we need to try to bind any time we see a component enable
+                        // state change, because that change may have made a transport available.
+                        // However, because we currently only support a single transport component
+                        // per package, we can skip the bind attempt if the change (a) affects a
+                        // package known to host a transport, but (b) does not affect the known
+                        // transport component itself.
+                        //
+                        // In addition, if the change *is* to a known transport component, we need
+                        // to unbind it before retrying the binding.
+                        boolean tryBind = true;
                         synchronized (mTransports) {
                             TransportConnection conn = mTransportConnections.get(pkgName);
                             if (conn != null) {
+                                // We have a bound transport in this package; do we need to rebind it?
                                 final ServiceInfo svc = conn.mTransport;
                                 ComponentName svcName =
                                         new ComponentName(svc.packageName, svc.name);
-                                String flatName = svcName.flattenToShortString();
-                                Slog.i(TAG, "Unbinding " + svcName);
-
-                                mContext.unbindService(conn);
-                                mTransportConnections.remove(pkgName);
-                                mTransports.remove(mTransportNames.get(flatName));
-                                mTransportNames.remove(flatName);
+                                if (svc.packageName.equals(pkgName)) {
+                                    final String className = svcName.getClassName();
+                                    if (MORE_DEBUG) {
+                                        Slog.i(TAG, "Checking need to rebind " + className);
+                                    }
+                                    // See whether it's the transport component within this package
+                                    boolean isTransport = false;
+                                    for (int i = 0; i < components.length; i++) {
+                                        if (className.equals(components[i])) {
+                                            // Okay, it's an existing transport component.
+                                            final String flatName = svcName.flattenToShortString();
+                                            mContext.unbindService(conn);
+                                            mTransportConnections.remove(pkgName);
+                                            mTransports.remove(mTransportNames.get(flatName));
+                                            mTransportNames.remove(flatName);
+                                            isTransport = true;
+                                            break;
+                                        }
+                                    }
+                                    if (!isTransport) {
+                                        // A non-transport component within a package that is hosting
+                                        // a bound transport
+                                        tryBind = false;
+                                    }
+                                }
                             }
                         }
-                        // and then (re)bind as appropriate
-                        PackageInfo app = mPackageManager.getPackageInfo(pkgName, 0);
-                        checkForTransportAndBind(app);
+                        // and now (re)bind as appropriate
+                        if (tryBind) {
+                            if (MORE_DEBUG) {
+                                Slog.i(TAG, "Yes, need to recheck binding");
+                            }
+                            PackageInfo app = mPackageManager.getPackageInfo(pkgName, 0);
+                            checkForTransportAndBind(app);
+                        }
                     } catch (NameNotFoundException e) {
                         // Nope, can't find it - just ignore
                         if (MORE_DEBUG) {
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 7d427d6..79c66b9 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -408,11 +408,19 @@
             }
         }
         if (repCbs != null) {
-            for (int i=0; i<repCbs.size(); i++) {
-                try {
-                    repCbs.get(i).mCallback.opChanged(code, packageName);
-                } catch (RemoteException e) {
+            // There are components watching for mode changes such as window manager
+            // and location manager which are in our process. The callbacks in these
+            // components may require permissions our remote caller does not have.
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                for (int i = 0; i < repCbs.size(); i++) {
+                    try {
+                        repCbs.get(i).mCallback.opChanged(code, packageName);
+                    } catch (RemoteException e) {
+                    }
                 }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
     }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index e00cf5b..d48953d 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -973,6 +973,7 @@
             }
         }
 
+        disk.volumeCount = volumeCount;
         mCallbacks.notifyDiskScanned(disk, volumeCount);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0ecdd61..28a786a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -369,11 +369,14 @@
     /** Permission grant: grant the permission as an install permission. */
     private static final int GRANT_INSTALL = 2;
 
+    /** Permission grant: grant the permission as an install permission for a legacy app. */
+    private static final int GRANT_INSTALL_LEGACY = 3;
+
     /** Permission grant: grant the permission as a runtime one. */
-    private static final int GRANT_RUNTIME = 3;
+    private static final int GRANT_RUNTIME = 4;
 
     /** Permission grant: grant as runtime a permission that was granted as an install time one. */
-    private static final int GRANT_UPGRADE = 4;
+    private static final int GRANT_UPGRADE = 5;
 
     final ServiceThread mHandlerThread;
 
@@ -4133,6 +4136,7 @@
 
         final int userId = UserHandle.getCallingUserId();
         ArrayList<ResolveInfo> result = new ArrayList<ResolveInfo>();
+        ArrayList<ResolveInfo> alwaysList = new ArrayList<ResolveInfo>();
         ArrayList<ResolveInfo> undefinedList = new ArrayList<ResolveInfo>();
         ArrayList<ResolveInfo> neverList = new ArrayList<ResolveInfo>();
         ArrayList<ResolveInfo> matchAllList = new ArrayList<ResolveInfo>();
@@ -4155,27 +4159,22 @@
                     // Try to get the status from User settings first
                     int status = getDomainVerificationStatusLPr(ps, userId);
                     if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
-                        result.add(info);
+                        alwaysList.add(info);
                     } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
                         neverList.add(info);
-                    } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+                    } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED ||
+                            status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK) {
                         undefinedList.add(info);
                     }
                 }
             }
-            // Add all undefined Apps as we want them to appear in the Disambiguation dialog.
-            result.addAll(undefinedList);
-            // If there is nothing selected, add all candidates and remove the ones that the User
-            // has explicitely put into the INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER state and
-            // also remove Browser Apps ones.
-            // If there is still none after this pass, add all Browser Apps and
-            // let the User decide with the Disambiguation dialog if there are several ones.
-            if (result.size() == 0) {
-                result.addAll(candidates);
-            }
-            result.removeAll(neverList);
-            result.removeAll(matchAllList);
-            if (result.size() == 0) {
+            // First try to add the "always" if there is any
+            if (alwaysList.size() > 0) {
+                result.addAll(alwaysList);
+            } else {
+                // Add all undefined Apps as we want them to appear in the Disambiguation dialog.
+                result.addAll(undefinedList);
+                // Also add Browsers (all of them or only the default one)
                 if ((flags & MATCH_ALL) != 0) {
                     result.addAll(matchAllList);
                 } else {
@@ -4200,6 +4199,13 @@
                         result.addAll(matchAllList);
                     }
                 }
+
+                // If there is nothing selected, add all candidates and remove the ones that the User
+                // has explicitely put into the INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER state
+                if (result.size() == 0) {
+                    result.addAll(candidates);
+                    result.removeAll(neverList);
+                }
             }
         }
         if (DEBUG_PREFERRED) {
@@ -7738,7 +7744,7 @@
                 case PermissionInfo.PROTECTION_DANGEROUS: {
                     if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
                         // For legacy apps dangerous permissions are install time ones.
-                        grant = GRANT_INSTALL;
+                        grant = GRANT_INSTALL_LEGACY;
                     } else if (ps.isSystem()) {
                         final int[] updatedUserIds = ps.getPermissionsUpdatedForUserIds();
                         if (origPermissions.hasInstallPermission(bp.name)) {
@@ -7798,6 +7804,28 @@
 
                 switch (grant) {
                     case GRANT_INSTALL: {
+                        // Revoke this as runtime permission to handle the case of
+                        // a runtime permssion being downgraded to an install one.
+                        for (int userId : UserManagerService.getInstance().getUserIds()) {
+                            if (origPermissions.getRuntimePermissionState(
+                                    bp.name, userId) != null) {
+                                // Revoke the runtime permission and clear the flags.
+                                origPermissions.revokeRuntimePermission(bp, userId);
+                                origPermissions.updatePermissionFlags(bp, userId,
+                                      PackageManager.MASK_PERMISSION_FLAGS, 0);
+                                // If we revoked a permission permission, we have to write.
+                                changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+                                        changedRuntimePermissionUserIds, userId);
+                            }
+                        }
+                        // Grant an install permission.
+                        if (permissionsState.grantInstallPermission(bp) !=
+                                PermissionsState.PERMISSION_OPERATION_FAILURE) {
+                            changedInstallPermission = true;
+                        }
+                    } break;
+
+                    case GRANT_INSTALL_LEGACY: {
                         // Grant an install permission.
                         if (permissionsState.grantInstallPermission(bp) !=
                                 PermissionsState.PERMISSION_OPERATION_FAILURE) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b84b506..d956d76 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3187,10 +3187,13 @@
                     }
                 }
                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
-                    // To change the format, we need to re-build the surface.
-                    winAnimator.destroySurfaceLocked();
-                    toBeDisplayed = true;
-                    surfaceChanged = true;
+                    // If the format can be changed in place yaay!
+                    // If not, fall back to a surface re-build
+                    if (!winAnimator.tryChangeFormatInPlaceLocked()) {
+                        winAnimator.destroySurfaceLocked();
+                        toBeDisplayed = true;
+                        surfaceChanged = true;
+                    }
                 }
                 try {
                     if (!win.mHasSurface) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 424e2e2..e9023fd 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -146,6 +146,9 @@
 
     boolean mKeyguardGoingAwayAnimation;
 
+    /** The pixel format of the underlying SurfaceControl */
+    int mSurfaceFormat;
+
     /** This is set when there is no Surface */
     static final int NO_SURFACE = 0;
     /** This is set after the Surface has been created but before the window has been drawn. During
@@ -845,6 +848,7 @@
                     flags |= SurfaceControl.OPAQUE;
                 }
 
+                mSurfaceFormat = format;
                 if (DEBUG_SURFACE_TRACE) {
                     mSurfaceControl = new SurfaceTrace(
                             mSession.mSurfaceSession,
@@ -1610,6 +1614,28 @@
         }
     }
 
+    /**
+     * Try to change the pixel format without recreating the surface. This
+     * will be common in the case of changing from PixelFormat.OPAQUE to
+     * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both
+     * requested formats resolve to the same underlying SurfaceControl format
+     * @return True if format was succesfully changed, false otherwise
+     */
+    boolean tryChangeFormatInPlaceLocked() {
+        if (mSurfaceControl == null) {
+            return false;
+        }
+        final LayoutParams attrs = mWin.getAttrs();
+        final boolean isHwAccelerated = (attrs.flags &
+                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
+        final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
+        if (format == mSurfaceFormat) {
+            setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
+            return true;
+        }
+        return false;
+    }
+
     void setOpaqueLocked(boolean isOpaque) {
         if (mSurfaceControl == null) {
             return;
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index f05a1ef..a25d327 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -151,6 +151,7 @@
     private final CharSequence mShortDescription;
     private final List<String> mSupportedUriSchemes;
     private final Icon mIcon;
+    private boolean mIsEnabled;
 
     /**
      * Helper class for creating a {@link PhoneAccount}.
@@ -165,6 +166,7 @@
         private CharSequence mShortDescription;
         private List<String> mSupportedUriSchemes = new ArrayList<String>();
         private Icon mIcon;
+        private boolean mIsEnabled = false;
 
         /**
          * Creates a builder with the specified {@link PhoneAccountHandle} and label.
@@ -190,6 +192,7 @@
             mShortDescription = phoneAccount.getShortDescription();
             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
             mIcon = phoneAccount.getIcon();
+            mIsEnabled = phoneAccount.isEnabled();
         }
 
         /**
@@ -288,6 +291,18 @@
         }
 
         /**
+         * Sets the enabled state of the phone account.
+         *
+         * @param isEnabled The enabled state.
+         * @return The builder.
+         * @hide
+         */
+        public Builder setIsEnabled(boolean isEnabled) {
+            mIsEnabled = isEnabled;
+            return this;
+        }
+
+        /**
          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
          *
          * @return The {@link PhoneAccount}.
@@ -307,7 +322,8 @@
                     mHighlightColor,
                     mLabel,
                     mShortDescription,
-                    mSupportedUriSchemes);
+                    mSupportedUriSchemes,
+                    mIsEnabled);
         }
     }
 
@@ -320,7 +336,8 @@
             int highlightColor,
             CharSequence label,
             CharSequence shortDescription,
-            List<String> supportedUriSchemes) {
+            List<String> supportedUriSchemes,
+            boolean isEnabled) {
         mAccountHandle = account;
         mAddress = address;
         mSubscriptionAddress = subscriptionAddress;
@@ -330,6 +347,7 @@
         mLabel = label;
         mShortDescription = shortDescription;
         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
+        mIsEnabled = isEnabled;
     }
 
     public static Builder builder(
@@ -437,6 +455,15 @@
     }
 
     /**
+     * Indicates whether the user has enabled this phone account or not {@code PhoneAccounts}.
+     *
+     * @return The {@code true} if the account is enabled by the user, {@code false} otherwise.
+     */
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    /**
      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
      * scheme.
      *
@@ -466,6 +493,14 @@
         return mHighlightColor;
     }
 
+    /**
+     * Sets the enabled state of the phone account.
+     * @hide
+     */
+    public void setIsEnabled(boolean isEnabled) {
+        mIsEnabled = isEnabled;
+    }
+
     //
     // Parcelable implementation
     //
@@ -500,12 +535,14 @@
         out.writeCharSequence(mLabel);
         out.writeCharSequence(mShortDescription);
         out.writeStringList(mSupportedUriSchemes);
+
         if (mIcon == null) {
             out.writeInt(0);
         } else {
             out.writeInt(1);
             mIcon.writeToParcel(out, flags);
         }
+        out.writeByte((byte) (mIsEnabled ? 1 : 0));
     }
 
     public static final Creator<PhoneAccount> CREATOR
@@ -547,11 +584,14 @@
         } else {
             mIcon = null;
         }
+        mIsEnabled = in.readByte() == 1;
     }
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder().append("[PhoneAccount: ")
+        StringBuilder sb = new StringBuilder().append("[[")
+                .append(mIsEnabled ? 'X' : ' ')
+                .append("] PhoneAccount: ")
                 .append(mAccountHandle)
                 .append(" Capabilities: ")
                 .append(mCapabilities)
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index c8ed2b0..308c204 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -377,15 +377,23 @@
     }
 
     /**
-     * Return the {@link PhoneAccount} which is the user-chosen default for making outgoing phone
-     * calls with a specified URI scheme.
+     * Return the {@link PhoneAccount} which will be used to place outgoing calls to addresses with
+     * the specified {@code uriScheme}. This {@link PhoneAccount} will always be a member of the
+     * list which is returned from invoking {@link #getCallCapablePhoneAccounts()}. The specific
+     * account returned depends on the following priorities:
+     * <ul>
+     * <li> If the user-selected default {@link PhoneAccount} supports the specified scheme, it will
+     * be returned.
+     * </li>
+     * <li> If there exists only one {@link PhoneAccount} that supports the specified scheme, it
+     * will be returned.
+     * </li>
+     * </ul>
      * <p>
-     * Apps must be prepared for this method to return {@code null}, indicating that there currently
-     * exists no user-chosen default {@code PhoneAccount}.
-     * <p>
+     * If no {@link PhoneAccount} fits the criteria above, this method will return {@code null}.
+     *
      * @param uriScheme The URI scheme.
-     * @return The {@link PhoneAccountHandle} corresponding to the user-chosen default for outgoing
-     * phone calls for a specified URI scheme.
+     * @return The {@link PhoneAccountHandle} corresponding to the account to be used.
      */
     public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
         try {
@@ -403,7 +411,7 @@
      * Return the {@link PhoneAccount} which is the user-chosen default for making outgoing phone
      * calls. This {@code PhoneAccount} will always be a member of the list which is returned from
      * calling {@link #getCallCapablePhoneAccounts()}
-     *
+     * <p>
      * Apps must be prepared for this method to return {@code null}, indicating that there currently
      * exists no user-chosen default {@code PhoneAccount}.
      *
@@ -422,7 +430,7 @@
     }
 
     /**
-     * Sets the default account for making outgoing phone calls.
+     * Sets the user-chosen default for making outgoing phone calls.
      * @hide
      */
     public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
@@ -439,6 +447,7 @@
      * Returns the current SIM call manager. Apps must be prepared for this method to return
      * {@code null}, indicating that there currently exists no user-chosen default
      * {@code PhoneAccount}.
+     *
      * @return The phone account handle of the current sim call manager.
      */
     public PhoneAccountHandle getSimCallManager() {
@@ -454,6 +463,7 @@
 
     /**
      * Sets the SIM call manager to the specified phone account.
+     *
      * @param accountHandle The phone account handle of the account to set as the sim call manager.
      * @hide
      */
@@ -469,6 +479,7 @@
 
     /**
      * Returns the list of registered SIM call managers.
+     *
      * @return List of registered SIM call managers.
      * @hide
      */
@@ -497,16 +508,6 @@
     }
 
     /**
-     * Returns the list of registered SIM call managers.
-     * @return List of registered SIM call managers.
-     * @hide
-     */
-    @SystemApi
-    public List<PhoneAccountHandle> getRegisteredConnectionManagers() {
-        return getSimCallManagers();
-    }
-
-    /**
      * Returns a list of the {@link PhoneAccountHandle}s which can be used to make and receive phone
      * calls which support the specified URI scheme.
      * <P>
@@ -534,20 +535,33 @@
 
 
     /**
-     * Return a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
-     * calls.
+     * Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
+     * calls. The returned list includes only those accounts which have been explicitly enabled
+     * by the user.
      *
      * @see #EXTRA_PHONE_ACCOUNT_HANDLE
      * @return A list of {@code PhoneAccountHandle} objects.
-     *
      */
     public List<PhoneAccountHandle> getCallCapablePhoneAccounts() {
+        return getCallCapablePhoneAccounts(false);
+    }
+
+    /**
+     * Returns a list of {@link PhoneAccountHandle}s including those which have not been enabled
+     * by the user.
+     *
+     * @return A list of {@code PhoneAccountHandle} objects.
+     * @hide
+     */
+    public List<PhoneAccountHandle> getCallCapablePhoneAccounts(boolean includeDisabledAccounts) {
         try {
             if (isServiceConnected()) {
-                return getTelecomService().getCallCapablePhoneAccounts(mContext.getOpPackageName());
+                return getTelecomService().getCallCapablePhoneAccounts(
+                        includeDisabledAccounts, mContext.getOpPackageName());
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts", e);
+            Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts(" +
+                    includeDisabledAccounts + ")", e);
         }
         return new ArrayList<>();
     }
@@ -1163,6 +1177,25 @@
         }
     }
 
+    /**
+     * Enables and disables specified phone account.
+     *
+     * @param handle Handle to the phone account.
+     * @param isEnabled Enable state of the phone account.
+     * @hide
+     */
+    @SystemApi
+    public void enablePhoneAccount(PhoneAccountHandle handle, boolean isEnabled) {
+        ITelecomService service = getTelecomService();
+        if (service != null) {
+            try {
+                service.enablePhoneAccount(handle, isEnabled);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error enablePhoneAbbount", e);
+            }
+        }
+    }
+
     private ITelecomService getTelecomService() {
         return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));
     }
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index bc76f06..aa02021 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -53,7 +53,8 @@
     /**
      * @see TelecomServiceImpl#getCallCapablePhoneAccounts
      */
-    List<PhoneAccountHandle> getCallCapablePhoneAccounts(String callingPackage);
+    List<PhoneAccountHandle> getCallCapablePhoneAccounts(
+            boolean includeDisabledAccounts, String callingPackage);
 
     /**
      * @see TelecomManager#getPhoneAccountsSupportingScheme
@@ -226,4 +227,9 @@
      * @see TelecomServiceImpl#placeCall
      */
     void placeCall(in Uri handle, in Bundle extras, String callingPackage);
+
+    /**
+     * @see TelecomServiceImpl#enablePhoneAccount
+     */
+    void enablePhoneAccount(in PhoneAccountHandle accountHandle, boolean isEnabled);
 }
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 572fdc9..771cf57 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -444,7 +444,7 @@
     @Override
     public int getDimensionPixelSize(int index, int defValue) {
         try {
-            return getDimension(index);
+            return getDimension(index, null);
         } catch (RuntimeException e) {
             String s = getString(index);
 
@@ -474,12 +474,12 @@
     @Override
     public int getLayoutDimension(int index, String name) {
         try {
-            // this will throw an exception
-            return getDimension(index);
+            // this will throw an exception if not found.
+            return getDimension(index, name);
         } catch (RuntimeException e) {
 
             if (LayoutInflater_Delegate.sIsInInclude) {
-                throw new RuntimeException();
+                throw new RuntimeException("Layout Dimension '" + name + "' not found.");
             }
 
             Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
@@ -494,9 +494,13 @@
         return getDimensionPixelSize(index, defValue);
     }
 
-    private int getDimension(int index) {
+    /** @param name attribute name, used for error reporting. */
+    private int getDimension(int index, @Nullable String name) {
         String s = getString(index);
         if (s == null) {
+            if (name != null) {
+                throw new RuntimeException("Attribute '" + name + "' not found");
+            }
             throw new RuntimeException();
         }
         // Check if the value is a magic constant that doesn't require a unit.
diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
index 4072302..27b406a 100644
--- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
@@ -181,7 +181,8 @@
                             // ---- END CHANGES
 
                             params = group.generateLayoutParams(attrs);
-
+                        } catch (RuntimeException ignored) {
+                            // Ignore, just fail over to child attrs.
                         } finally {
                             // ---- START CHANGES
                             sIsInInclude = false;