Merge "Update visibility of the stack dropdown list after the search view is collapsed." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index fb60f1c..803d2fd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7721,6 +7721,7 @@
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
     method public final T getSystemService(java.lang.Class<T>);
+    method public abstract java.lang.String getSystemServiceName(java.lang.Class<?>);
     method public final java.lang.CharSequence getText(int);
     method public abstract android.content.res.Resources.Theme getTheme();
     method public abstract deprecated android.graphics.drawable.Drawable getWallpaper();
@@ -17210,7 +17211,7 @@
     method public void connect();
     method public void disconnect();
     method public android.os.Bundle getExtras();
-    method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
+    method public void getItem(java.lang.String, android.media.browse.MediaBrowser.ItemCallback);
     method public java.lang.String getRoot();
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
@@ -17226,6 +17227,12 @@
     method public void onConnectionSuspended();
   }
 
+  public static abstract class MediaBrowser.ItemCallback {
+    ctor public MediaBrowser.ItemCallback();
+    method public void onError(java.lang.String);
+    method public void onItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+  }
+
   public static class MediaBrowser.MediaItem implements android.os.Parcelable {
     ctor public MediaBrowser.MediaItem(android.media.MediaDescription, int);
     method public int describeContents();
@@ -17240,12 +17247,6 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
-  public static abstract class MediaBrowser.MediaItemCallback {
-    ctor public MediaBrowser.MediaItemCallback();
-    method public void onError();
-    method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
-  }
-
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -28787,12 +28788,12 @@
   public abstract class MediaBrowserService extends android.app.Service {
     ctor public MediaBrowserService();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
     method public android.media.session.MediaSession.Token getSessionToken();
     method public void notifyChildrenChanged(java.lang.String);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
     method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
+    method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>);
     method public void setSessionToken(android.media.session.MediaSession.Token);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
   }
@@ -30735,7 +30736,7 @@
     field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
     field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
     field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
-    field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_BOOL = "voice_privacy_disable_bool";
+    field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
     field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 7816c3f..72e4142 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7944,6 +7944,7 @@
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
     method public final T getSystemService(java.lang.Class<T>);
+    method public abstract java.lang.String getSystemServiceName(java.lang.Class<?>);
     method public final java.lang.CharSequence getText(int);
     method public abstract android.content.res.Resources.Theme getTheme();
     method public abstract deprecated android.graphics.drawable.Drawable getWallpaper();
@@ -18522,7 +18523,7 @@
     method public void connect();
     method public void disconnect();
     method public android.os.Bundle getExtras();
-    method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
+    method public void getItem(java.lang.String, android.media.browse.MediaBrowser.ItemCallback);
     method public java.lang.String getRoot();
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
@@ -18538,6 +18539,12 @@
     method public void onConnectionSuspended();
   }
 
+  public static abstract class MediaBrowser.ItemCallback {
+    ctor public MediaBrowser.ItemCallback();
+    method public void onError(java.lang.String);
+    method public void onItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+  }
+
   public static class MediaBrowser.MediaItem implements android.os.Parcelable {
     ctor public MediaBrowser.MediaItem(android.media.MediaDescription, int);
     method public int describeContents();
@@ -18552,12 +18559,6 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
-  public static abstract class MediaBrowser.MediaItemCallback {
-    ctor public MediaBrowser.MediaItemCallback();
-    method public void onError();
-    method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
-  }
-
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -19194,7 +19195,9 @@
     method public android.content.Intent createSettingsIntent();
     method public android.content.Intent createSetupIntent();
     method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.hardware.hdmi.HdmiDeviceInfo, java.lang.String, java.lang.String, android.net.Uri) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.hardware.hdmi.HdmiDeviceInfo, java.lang.String, int, android.graphics.drawable.Icon) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.media.tv.TvInputHardwareInfo, java.lang.String, android.net.Uri) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.media.tv.TvInputHardwareInfo, int, android.graphics.drawable.Icon) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
     method public android.hardware.hdmi.HdmiDeviceInfo getHdmiDeviceInfo();
     method public java.lang.String getId();
@@ -30820,12 +30823,12 @@
   public abstract class MediaBrowserService extends android.app.Service {
     ctor public MediaBrowserService();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
     method public android.media.session.MediaSession.Token getSessionToken();
     method public void notifyChildrenChanged(java.lang.String);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
     method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
+    method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>);
     method public void setSessionToken(android.media.session.MediaSession.Token);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
   }
@@ -32951,7 +32954,7 @@
     field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
     field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
     field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
-    field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_BOOL = "voice_privacy_disable_bool";
+    field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
     field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 49ac062..fd1e24a 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -28,6 +28,11 @@
 import java.util.HashMap;
 import java.util.Map;
 
+/**
+ * Represents a single operation to be performed as part of a batch of operations.
+ *
+ * @see ContentProvider#applyBatch(ArrayList)
+ */
 public class ContentProviderOperation implements Parcelable {
     /** @hide exposed for unit tests */
     public final static int TYPE_INSERT = 1;
@@ -195,10 +200,19 @@
         return new Builder(TYPE_ASSERT, uri);
     }
 
+    /**
+     * Gets the Uri for the target of the operation.
+     */
     public Uri getUri() {
         return mUri;
     }
 
+    /**
+     * Returns true if the operation allows yielding the database to other transactions
+     * if the database is contended.
+     *
+     * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
+     */
     public boolean isYieldAllowed() {
         return mYieldAllowed;
     }
@@ -208,26 +222,58 @@
         return mType;
     }
 
+    /**
+     * Returns true if the operation represents an insertion.
+     *
+     * @see #newInsert
+     */
     public boolean isInsert() {
         return mType == TYPE_INSERT;
     }
 
+    /**
+     * Returns true if the operation represents a deletion.
+     *
+     * @see #newDelete
+     */
     public boolean isDelete() {
         return mType == TYPE_DELETE;
     }
 
+    /**
+     * Returns true if the operation represents an update.
+     *
+     * @see #newUpdate
+     */
     public boolean isUpdate() {
         return mType == TYPE_UPDATE;
     }
 
+    /**
+     * Returns true if the operation represents an assert query.
+     *
+     * @see #newAssertQuery
+     */
     public boolean isAssertQuery() {
         return mType == TYPE_ASSERT;
     }
 
+    /**
+     * Returns true if the operation represents an insertion, deletion, or update.
+     *
+     * @see #isInsert
+     * @see #isDelete
+     * @see #isUpdate
+     */
     public boolean isWriteOperation() {
         return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE;
     }
 
+    /**
+     * Returns true if the operation represents an assert query.
+     *
+     * @see #isAssertQuery
+     */
     public boolean isReadOperation() {
         return mType == TYPE_ASSERT;
     }
@@ -617,7 +663,7 @@
         }
 
         /**
-         * If set then if the number of rows affected by this operation do not match
+         * If set then if the number of rows affected by this operation does not match
          * this count {@link OperationApplicationException} will be throw.
          * This can only be used with builders of type update, delete, or assert.
          * @return this builder, to allow for chaining.
@@ -631,6 +677,12 @@
             return this;
         }
 
+        /**
+         * If set to true then the operation allows yielding the database to other transactions
+         * if the database is contended.
+         * @return this builder, to allow for chaining.
+         * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
+         */
         public Builder withYieldAllowed(boolean yieldAllowed) {
             mYieldAllowed = yieldAllowed;
             return this;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a434c7b..33f38fb 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2443,8 +2443,6 @@
      *
      * @param serviceClass The class of the desired service.
      * @return The service name or null if the class is not a supported system service.
-     *
-     * @hide
      */
     public abstract String getSystemServiceName(Class<?> serviceClass);
 
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index e47220b..5f46c73 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -24,8 +24,13 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Protocol;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * A NetworkFactory is an entity that creates NetworkAgent objects.
  * The bearers register with ConnectivityService using {@link #register} and
@@ -157,6 +162,11 @@
             this.score = score;
             this.requested = false;
         }
+
+        @Override
+        public String toString() {
+            return "{" + request + ", score=" + score + ", requested=" + requested + "}";
+        }
     }
 
     private void handleAddRequest(NetworkRequest request, int score) {
@@ -176,9 +186,9 @@
 
     private void handleRemoveRequest(NetworkRequest request) {
         NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
-        if (n != null && n.requested) {
+        if (n != null) {
             mNetworkRequests.remove(request.requestId);
-            releaseNetworkFor(n.request);
+            if (n.requested) releaseNetworkFor(n.request);
         }
     }
 
@@ -273,15 +283,31 @@
         sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
     }
 
+    @VisibleForTesting
+    protected int getRequestCount() {
+        return mNetworkRequests.size();
+    }
+
     protected void log(String s) {
         Log.d(LOG_TAG, s);
     }
 
+    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
+        pw.println(toString());
+        pw.increaseIndent();
+        for (int i = 0; i < mNetworkRequests.size(); i++) {
+            pw.println(mNetworkRequests.valueAt(i));
+        }
+        pw.decreaseIndent();
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - ScoreFilter=").
                 append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=").
-                append(mNetworkRequests.size()).append("}");
+                append(mNetworkRequests.size()).append(", refCount=").append(mRefCount).
+                append("}");
         return sb.toString();
     }
 }
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 89d419a..6c26220 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1382,7 +1382,7 @@
             // upper limit.
             // for now we are keeping the profile specific "width/height
             // in macroblocks" limits.
-            if (Integer.valueOf(1).equals(map.get("feature-can-swap-width-height"))) {
+            if (map.containsKey("feature-can-swap-width-height")) {
                 if (widths != null) {
                     mSmallerDimensionUpperLimit =
                         Math.min(widths.getUpper(), heights.getUpper());
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index ef8d169..ba867e1 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -375,7 +375,7 @@
      * @param mediaId The id of the item to retrieve.
      * @param cb The callback to receive the result on.
      */
-    public void getMediaItem(@NonNull String mediaId, @NonNull final MediaItemCallback cb) {
+    public void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb) {
         if (TextUtils.isEmpty(mediaId)) {
             throw new IllegalArgumentException("mediaId is empty.");
         }
@@ -387,7 +387,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    cb.onError();
+                    cb.onError(mediaId);
                 }
             });
             return;
@@ -397,15 +397,15 @@
             protected void onReceiveResult(int resultCode, Bundle resultData) {
                 if (resultCode != 0 || resultData == null
                         || !resultData.containsKey(MediaBrowserService.KEY_MEDIA_ITEM)) {
-                    cb.onError();
+                    cb.onError(mediaId);
                     return;
                 }
                 Parcelable item = resultData.getParcelable(MediaBrowserService.KEY_MEDIA_ITEM);
                 if (!(item instanceof MediaItem)) {
-                    cb.onError();
+                    cb.onError(mediaId);
+                    return;
                 }
-                cb.onMediaItemLoaded((MediaItem) resultData.getParcelable(
-                        MediaBrowserService.KEY_MEDIA_ITEM));
+                cb.onItemLoaded((MediaItem)item);
             }
         };
         try {
@@ -415,7 +415,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    cb.onError();
+                    cb.onError(mediaId);
                 }
             });
         }
@@ -728,6 +728,9 @@
     public static abstract class SubscriptionCallback {
         /**
          * Called when the list of children is loaded or updated.
+         *
+         * @param parentId The media id of the parent media item.
+         * @param children The children which were loaded.
          */
         public void onChildrenLoaded(@NonNull String parentId,
                                      @NonNull List<MediaItem> children) {
@@ -739,29 +742,32 @@
          * If this is called, the subscription remains until {@link MediaBrowser#unsubscribe}
          * called, because some errors may heal themselves.
          * </p>
+         *
+         * @param parentId The media id of the parent media item whose children could
+         * not be loaded.
          */
-        public void onError(@NonNull String id) {
+        public void onError(@NonNull String parentId) {
         }
     }
 
     /**
-     * Callback for receiving the result of {@link #getMediaItem}.
+     * Callback for receiving the result of {@link #getItem}.
      */
-    public static abstract class MediaItemCallback {
-
+    public static abstract class ItemCallback {
         /**
          * Called when the item has been returned by the browser service.
          *
          * @param item The item that was returned or null if it doesn't exist.
          */
-        public void onMediaItemLoaded(MediaItem item) {
+        public void onItemLoaded(MediaItem item) {
         }
 
         /**
-         * Called when the id doesn't exist or there was an error retrieving the
-         * item.
+         * Called when the item doesn't exist or there was an error retrieving it.
+         *
+         * @param itemId The media id of the media item which could not be loaded.
          */
-        public void onError() {
+        public void onError(@NonNull String itemId) {
         }
     }
 
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index c537dd6..5d1aa14 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -29,6 +29,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.net.Uri;
 import android.os.Parcel;
@@ -125,7 +126,9 @@
     private String mSettingsActivity;
 
     private HdmiDeviceInfo mHdmiDeviceInfo;
+    private int mLabelRes;
     private String mLabel;
+    private Icon mIcon;
     private Uri mIconUri;
     private boolean mIsConnectedToHdmiSwitch;
 
@@ -155,7 +158,7 @@
             throws XmlPullParserException, IOException {
         return createTvInputInfo(context, service, generateInputIdForComponentName(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name)),
-                null, TYPE_TUNER, false, null, null, false);
+                null, TYPE_TUNER, false, 0, null, null, null, false);
     }
 
     /**
@@ -165,11 +168,11 @@
      * @param service The ResolveInfo returned from the package manager about this TV input service.
      * @param hdmiDeviceInfo The HdmiDeviceInfo for a HDMI CEC logical device.
      * @param parentId The ID of this TV input's parent input. {@code null} if none exists.
+     * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
+     *            label will be loaded.
      * @param iconUri The {@link android.net.Uri} to load the icon image. See
      *            {@link android.content.ContentResolver#openInputStream}. If it is {@code null},
      *            the application icon of {@code service} will be loaded.
-     * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
-     *            label will be loaded.
      * @hide
      */
     @SystemApi
@@ -179,7 +182,34 @@
         boolean isConnectedToHdmiSwitch = (hdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
         TvInputInfo input = createTvInputInfo(context, service, generateInputIdForHdmiDevice(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
-                hdmiDeviceInfo), parentId, TYPE_HDMI, true, label, iconUri, isConnectedToHdmiSwitch);
+                hdmiDeviceInfo), parentId, TYPE_HDMI, true, 0, label, null, iconUri,
+                isConnectedToHdmiSwitch);
+        input.mHdmiDeviceInfo = hdmiDeviceInfo;
+        return input;
+    }
+
+    /**
+     * Create a new instance of the TvInputInfo class, instantiating it from the given Context,
+     * ResolveInfo, and HdmiDeviceInfo.
+     *
+     * @param service The ResolveInfo returned from the package manager about this TV input service.
+     * @param hdmiDeviceInfo The HdmiDeviceInfo for a HDMI CEC logical device.
+     * @param parentId The ID of this TV input's parent input. {@code null} if none exists.
+     * @param labelRes The label resource ID of this TvInputInfo. If it is {@code 0},
+     *            {@code service} label will be loaded.
+     * @param icon The {@link android.graphics.drawable.Icon} to load the icon image. If it is
+     *            {@code null}, the application icon of {@code service} will be loaded.
+     * @hide
+     */
+    @SystemApi
+    public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
+            HdmiDeviceInfo hdmiDeviceInfo, String parentId, int labelRes, Icon icon)
+            throws XmlPullParserException, IOException {
+        boolean isConnectedToHdmiSwitch = (hdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
+        TvInputInfo input = createTvInputInfo(context, service, generateInputIdForHdmiDevice(
+                new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
+                hdmiDeviceInfo), parentId, TYPE_HDMI, true, labelRes, null, icon, null,
+                isConnectedToHdmiSwitch);
         input.mHdmiDeviceInfo = hdmiDeviceInfo;
         return input;
     }
@@ -190,11 +220,11 @@
      *
      * @param service The ResolveInfo returned from the package manager about this TV input service.
      * @param hardwareInfo The TvInputHardwareInfo for a TV input hardware device.
+     * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
+     *            label will be loaded.
      * @param iconUri The {@link android.net.Uri} to load the icon image. See
      *            {@link android.content.ContentResolver#openInputStream}. If it is {@code null},
      *            the application icon of {@code service} will be loaded.
-     * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
-     *            label will be loaded.
      * @hide
      */
     @SystemApi
@@ -204,12 +234,34 @@
         int inputType = sHardwareTypeToTvInputType.get(hardwareInfo.getType(), TYPE_TUNER);
         return createTvInputInfo(context, service, generateInputIdForHardware(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
-                hardwareInfo), null, inputType, true, label, iconUri, false);
+                hardwareInfo), null, inputType, true, 0, label, null, iconUri, false);
     }
 
-    private static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
-            String id, String parentId, int inputType, boolean isHardwareInput, String label,
-            Uri iconUri, boolean isConnectedToHdmiSwitch)
+    /**
+     * Create a new instance of the TvInputInfo class, instantiating it from the given Context,
+     * ResolveInfo, and TvInputHardwareInfo.
+     *
+     * @param service The ResolveInfo returned from the package manager about this TV input service.
+     * @param hardwareInfo The TvInputHardwareInfo for a TV input hardware device.
+     * @param labelRes The label resource ID of this TvInputInfo. If it is {@code 0},
+     *            {@code service} label will be loaded.
+     * @param icon The {@link android.graphics.drawable.Icon} to load the icon image. If it is
+     *            {@code null}, the application icon of {@code service} will be loaded.
+     * @hide
+     */
+    @SystemApi
+    public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
+            TvInputHardwareInfo hardwareInfo, int labelRes, Icon icon)
+            throws XmlPullParserException, IOException {
+        int inputType = sHardwareTypeToTvInputType.get(hardwareInfo.getType(), TYPE_TUNER);
+        return createTvInputInfo(context, service, generateInputIdForHardware(
+                new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
+                hardwareInfo), null, inputType, true, labelRes, null, icon, null, false);
+    }
+
+    private static TvInputInfo createTvInputInfo(Context context, ResolveInfo service, String id,
+            String parentId, int inputType, boolean isHardwareInput, int labelRes, String label,
+            Icon icon, Uri iconUri, boolean isConnectedToHdmiSwitch)
                     throws XmlPullParserException, IOException {
         ServiceInfo si = service.serviceInfo;
         PackageManager pm = context.getPackageManager();
@@ -254,7 +306,9 @@
             }
             sa.recycle();
 
+            input.mLabelRes = labelRes;
             input.mLabel = label;
+            input.mIcon = icon;
             input.mIconUri = iconUri;
             input.mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
             return input;
@@ -426,11 +480,13 @@
      *         a label, its name is returned.
      */
     public CharSequence loadLabel(@NonNull Context context) {
-        if (TextUtils.isEmpty(mLabel)) {
-            return mService.loadLabel(context.getPackageManager());
-        } else {
+        if (mLabelRes != 0) {
+            return context.getPackageManager().getText(mService.serviceInfo.packageName, mLabelRes,
+                    null);
+        } else if (!TextUtils.isEmpty(mLabel)) {
             return mLabel;
         }
+        return mService.loadLabel(context.getPackageManager());
     }
 
     /**
@@ -454,19 +510,20 @@
      *         application's icon is returned. If it's unavailable too, {@code null} is returned.
      */
     public Drawable loadIcon(@NonNull Context context) {
-        if (mIconUri == null) {
-            return loadServiceIcon(context);
-        }
-        try (InputStream is = context.getContentResolver().openInputStream(mIconUri)) {
-            Drawable drawable = Drawable.createFromStream(is, null);
-            if (drawable == null) {
-                return loadServiceIcon(context);
+        if (mIcon != null) {
+            return mIcon.loadDrawable(context);
+        } else if (mIconUri != null) {
+            try (InputStream is = context.getContentResolver().openInputStream(mIconUri)) {
+                Drawable drawable = Drawable.createFromStream(is, null);
+                if (drawable != null) {
+                    return drawable;
+                }
+            } catch (IOException e) {
+                Log.w(TAG, "Loading the default icon due to a failure on loading " + mIconUri, e);
+                // Falls back.
             }
-            return drawable;
-        } catch (IOException e) {
-            Log.w(TAG, "Loading the default icon due to a failure on loading " + mIconUri, e);
-            return loadServiceIcon(context);
         }
+        return loadServiceIcon(context);
     }
 
     @Override
@@ -516,7 +573,9 @@
         dest.writeInt(mType);
         dest.writeByte(mIsHardwareInput ? (byte) 1 : 0);
         dest.writeParcelable(mHdmiDeviceInfo, flags);
+        dest.writeParcelable(mIcon, flags);
         dest.writeParcelable(mIconUri, flags);
+        dest.writeInt(mLabelRes);
         dest.writeString(mLabel);
         dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
     }
@@ -591,7 +650,9 @@
         mType = in.readInt();
         mIsHardwareInput = in.readByte() == 1 ? true : false;
         mHdmiDeviceInfo = in.readParcelable(null);
+        mIcon = in.readParcelable(null);
         mIconUri = in.readParcelable(null);
+        mLabelRes = in.readInt();
         mLabel = in.readString();
         mIsConnectedToHdmiSwitch = in.readByte() == 1 ? true : false;
     }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 41156cb..1bb99ff 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -76,7 +76,7 @@
     public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
 
     /**
-     * A key for passing the MediaItem to the ResultReceiver in getMediaItem.
+     * A key for passing the MediaItem to the ResultReceiver in getItem.
      *
      * @hide
      */
@@ -109,6 +109,7 @@
      * be thrown.
      *
      * @see MediaBrowserService#onLoadChildren
+     * @see MediaBrowserService#onGetMediaItem
      */
     public class Result<T> {
         private Object mDebug;
@@ -279,20 +280,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    final Result<MediaBrowser.MediaItem> result
-                            = new Result<MediaBrowser.MediaItem>(mediaId) {
-                        @Override
-                        void onResultSent(MediaBrowser.MediaItem item) {
-                            Bundle bundle = new Bundle();
-                            bundle.putParcelable(KEY_MEDIA_ITEM, item);
-                            receiver.send(0, bundle);
-                        }
-                    };
-                    try {
-                        MediaBrowserService.this.getMediaItem(mediaId, result);
-                    } catch (UnsupportedOperationException e) {
-                        receiver.send(-1, null);
-                    }
+                    performLoadItem(mediaId, receiver);
                 }
             });
         }
@@ -357,8 +345,7 @@
             @NonNull Result<List<MediaBrowser.MediaItem>> result);
 
     /**
-     * Called to get a specific media item. The mediaId should be the same id
-     * that would be returned for this item when it is in a list of child items.
+     * Called to get information about a specific media item.
      * <p>
      * Implementations must call {@link Result#sendResult result.sendResult}. If
      * loading the item will be an expensive operation {@link Result#detach
@@ -366,17 +353,15 @@
      * then {@link Result#sendResult result.sendResult} called when the item has
      * been loaded.
      * <p>
-     * The default implementation throws an exception.
+     * The default implementation sends a null result.
      *
-     * @param mediaId The id for the specific
+     * @param itemId The id for the specific
      *            {@link android.media.browse.MediaBrowser.MediaItem}.
      * @param result The Result to send the item to, or null if the id is
      *            invalid.
-     * @throws UnsupportedOperationException
      */
-    public void getMediaItem(String mediaId, Result<MediaBrowser.MediaItem> result)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException("getMediaItem is not supported.");
+    public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
+        result.sendResult(null);
     }
 
     /**
@@ -515,6 +500,25 @@
         }
     }
 
+    private void performLoadItem(String itemId, final ResultReceiver receiver) {
+        final Result<MediaBrowser.MediaItem> result =
+                new Result<MediaBrowser.MediaItem>(itemId) {
+            @Override
+            void onResultSent(MediaBrowser.MediaItem item) {
+                Bundle bundle = new Bundle();
+                bundle.putParcelable(KEY_MEDIA_ITEM, item);
+                receiver.send(0, bundle);
+            }
+        };
+
+        MediaBrowserService.this.onLoadItem(itemId, result);
+
+        if (!result.isDone()) {
+            throw new IllegalStateException("onLoadItem must call detach() or sendResult()"
+                    + " before returning for id=" + itemId);
+        }
+    }
+
     /**
      * Contains information that the browser service needs to send to the client
      * when first connected.
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 6684be4..bb0a36f 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -48,6 +48,7 @@
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
 import android.net.NetworkConfig;
+import android.net.NetworkFactory;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
@@ -55,6 +56,7 @@
 import android.net.RouteInfo;
 import android.os.ConditionVariable;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.INetworkManagementService;
 import android.test.AndroidTestCase;
@@ -68,6 +70,7 @@
 
 import java.net.InetAddress;
 import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Tests for {@link ConnectivityService}.
@@ -224,6 +227,31 @@
         }
     }
 
+    private static class MockNetworkFactory extends NetworkFactory {
+        final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
+
+        public MockNetworkFactory(Looper looper, Context context, String logTag,
+                NetworkCapabilities filter) {
+            super(looper, context, logTag, filter);
+        }
+
+        public int getMyRequestCount() {
+            return getRequestCount();
+        }
+
+        protected void startNetwork() {
+            mNetworkStarted.set(true);
+        }
+
+        protected void stopNetwork() {
+            mNetworkStarted.set(false);
+        }
+
+        public boolean getMyStartRequested() {
+            return mNetworkStarted.get();
+        }
+    }
+
     private class WrappedConnectivityService extends ConnectivityService {
         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
                 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
@@ -447,6 +475,71 @@
         verifyNoNetwork();
     }
 
+    @LargeTest
+    public void testNetworkFactoryRequests() throws Exception {
+        NetworkCapabilities filter = new NetworkCapabilities();
+        filter.addCapability(NET_CAPABILITY_INTERNET);
+        final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
+        handlerThread.start();
+        MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+                mServiceContext, "testFactory", filter);
+        testFactory.setScoreFilter(40);
+        testFactory.register();
+        try {
+            Thread.sleep(500);
+        } catch (Exception e) {}
+        assertEquals(1, testFactory.getMyRequestCount());
+        assertEquals(true, testFactory.getMyStartRequested());
+
+        // now bring in a higher scored network
+        MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        ConditionVariable cv = waitForConnectivityBroadcasts(1);
+        testAgent.connect(true);
+        cv.block();
+        // part of the bringup makes another network request and then releases it
+        // wait for the release
+        try { Thread.sleep(500); } catch (Exception e) {}
+        assertEquals(1, testFactory.getMyRequestCount());
+        assertEquals(false, testFactory.getMyStartRequested());
+
+        // bring in a bunch of requests..
+        ConnectivityManager.NetworkCallback[] networkCallbacks =
+                new ConnectivityManager.NetworkCallback[10];
+        for (int i = 0; i< networkCallbacks.length; i++) {
+            networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
+            NetworkRequest.Builder builder = new NetworkRequest.Builder();
+            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+            mCm.requestNetwork(builder.build(), networkCallbacks[i]);
+        }
+
+        try {
+            Thread.sleep(1000);
+        } catch (Exception e) {}
+        assertEquals(11, testFactory.getMyRequestCount());
+        assertEquals(false, testFactory.getMyStartRequested());
+
+        // remove the requests
+        for (int i = 0; i < networkCallbacks.length; i++) {
+            mCm.unregisterNetworkCallback(networkCallbacks[i]);
+        }
+        try {
+            Thread.sleep(500);
+        } catch (Exception e) {}
+        assertEquals(1, testFactory.getMyRequestCount());
+        assertEquals(false, testFactory.getMyStartRequested());
+
+        // drop the higher scored network
+        cv = waitForConnectivityBroadcasts(1);
+        testAgent.disconnect();
+        cv.block();
+        assertEquals(1, testFactory.getMyRequestCount());
+        assertEquals(true, testFactory.getMyStartRequested());
+
+        testFactory.unregister();
+        handlerThread.quit();
+    }
+
+
 //    @Override
 //    public void tearDown() throws Exception {
 //        super.tearDown();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b74b52d..6de438c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -124,7 +124,7 @@
             KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
 
     /** If true, removes the Voice Privacy option from Call Settings */
-    public static final String KEY_VOICE_PRIVACY_DISABLE_BOOL = "voice_privacy_disable_bool";
+    public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
 
     /** Control whether users can reach the carrier portions of Cellular Network Settings. */
     public static final String
@@ -302,7 +302,7 @@
         sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
         sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
         sDefaults.putBoolean(KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL, false);
-        sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_BOOL, false);
+        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_VVM_DESTINATION_NUMBER_STRING, "");