Merge "Add @UnsupportedAppUsage annotations"
diff --git a/Android.bp b/Android.bp
index 2e3073f..ae0acad 100644
--- a/Android.bp
+++ b/Android.bp
@@ -898,6 +898,7 @@
         "core/java/android/os/IHwInterface.java",
         "core/java/android/os/DeadObjectException.java",
         "core/java/android/os/DeadSystemException.java",
+        "core/java/android/os/NativeHandle.java",
         "core/java/android/os/RemoteException.java",
         "core/java/android/util/AndroidException.java",
     ],
@@ -1444,6 +1445,7 @@
         "core/java/android/os/IHwInterface.java",
         "core/java/android/os/DeadObjectException.java",
         "core/java/android/os/DeadSystemException.java",
+        "core/java/android/os/NativeHandle.java",
         "core/java/android/os/RemoteException.java",
         "core/java/android/util/AndroidException.java",
     ],
@@ -1572,6 +1574,7 @@
     metalava_previous_api: ":public-api-for-metalava-annotations",
     metalava_merge_annotations_dirs: [
         "metalava-manual",
+        "ojluni-annotated-stubs",
     ],
 }
 
diff --git a/api/current.txt b/api/current.txt
index 139776b..4ec2265 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -57590,14 +57590,14 @@
     method public void setContextClassLoader(java.lang.ClassLoader);
     method public final void setDaemon(boolean);
     method public static void setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler);
-    method public final void setName(java.lang.String);
+    method public final synchronized void setName(java.lang.String);
     method public final void setPriority(int);
     method public void setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler);
     method public static void sleep(long) throws java.lang.InterruptedException;
     method public static void sleep(long, int) throws java.lang.InterruptedException;
     method public synchronized void start();
     method public final deprecated void stop();
-    method public final deprecated void stop(java.lang.Throwable);
+    method public final deprecated synchronized void stop(java.lang.Throwable);
     method public final deprecated void suspend();
     method public static void yield();
     field public static final int MAX_PRIORITY = 10; // 0xa
diff --git a/api/system-current.txt b/api/system-current.txt
index a8e8dcb..859ee98 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3726,6 +3726,7 @@
     method public final void putInt64Array(long, long[]);
     method public final void putInt8(long, byte);
     method public final void putInt8Array(long, byte[]);
+    method public final void putNativeHandle(long, android.os.NativeHandle);
     method public final void putString(long, java.lang.String);
     method public static java.lang.Boolean[] wrapArray(boolean[]);
     method public static java.lang.Long[] wrapArray(long[]);
@@ -3745,6 +3746,7 @@
     method public final double readDouble();
     method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
     method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
+    method public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
     method public final float readFloat();
     method public final java.util.ArrayList<java.lang.Float> readFloatVector();
     method public final short readInt16();
@@ -3755,6 +3757,8 @@
     method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
     method public final byte readInt8();
     method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
+    method public final android.os.NativeHandle readNativeHandle();
+    method public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
     method public final java.lang.String readString();
     method public final java.util.ArrayList<java.lang.String> readStringVector();
     method public final android.os.IHwBinder readStrongBinder();
@@ -3778,6 +3782,8 @@
     method public final void writeInt8(byte);
     method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
     method public final void writeInterfaceToken(java.lang.String);
+    method public final void writeNativeHandle(android.os.NativeHandle);
+    method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
     method public final void writeStatus(int);
     method public final void writeString(java.lang.String);
     method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
@@ -3822,6 +3828,18 @@
     field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
   }
 
+  public final class NativeHandle implements java.io.Closeable {
+    ctor public NativeHandle();
+    ctor public NativeHandle(java.io.FileDescriptor, boolean);
+    ctor public NativeHandle(java.io.FileDescriptor[], int[], boolean);
+    method public void close() throws java.io.IOException;
+    method public android.os.NativeHandle dup() throws java.io.IOException;
+    method public java.io.FileDescriptor getFileDescriptor();
+    method public java.io.FileDescriptor[] getFileDescriptors();
+    method public int[] getInts();
+    method public boolean hasSingleFileDescriptor();
+  }
+
   public final class PowerManager {
     method public void userActivity(long, int, int);
     field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
diff --git a/api/test-current.txt b/api/test-current.txt
index 4c3c0f8..8073341 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -256,8 +256,8 @@
   public abstract class PackageManager {
     method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
     method public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
-    method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
     method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
+    method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
     method public abstract java.lang.String[] getNamesForUids(int[]);
     method public abstract java.lang.String getPermissionControllerPackageName();
     method public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
diff --git a/cmds/incident_helper/src/ih_util.cpp b/cmds/incident_helper/src/ih_util.cpp
index 4c4d1b9..012310c 100644
--- a/cmds/incident_helper/src/ih_util.cpp
+++ b/cmds/incident_helper/src/ih_util.cpp
@@ -97,7 +97,7 @@
 
     size_t lastIndex = 0;
     int i = 0;
-    while (headerNames[i] != NULL) {
+    while (headerNames[i] != nullptr) {
         std::string s = headerNames[i];
         lastIndex = line.find(s, lastIndex);
         if (lastIndex == std::string::npos) {
@@ -237,18 +237,18 @@
 Reader::Reader(const int fd)
 {
     mFile = fdopen(fd, "r");
-    mStatus = mFile == NULL ? "Invalid fd " + std::to_string(fd) : "";
+    mStatus = mFile == nullptr ? "Invalid fd " + std::to_string(fd) : "";
 }
 
 Reader::~Reader()
 {
-    if (mFile != NULL) fclose(mFile);
+    if (mFile != nullptr) fclose(mFile);
 }
 
 bool Reader::readLine(std::string* line) {
-    if (mFile == NULL) return false;
+    if (mFile == nullptr) return false;
 
-    char* buf = NULL;
+    char* buf = nullptr;
     size_t len = 0;
     ssize_t read = getline(&buf, &len, mFile);
     if (read != -1) {
diff --git a/cmds/incident_helper/src/main.cpp b/cmds/incident_helper/src/main.cpp
index 418dc3f..091410b 100644
--- a/cmds/incident_helper/src/main.cpp
+++ b/cmds/incident_helper/src/main.cpp
@@ -97,7 +97,7 @@
 
     fprintf(stderr, "Pasring section %d...\n", sectionID);
     TextParserBase* parser = selectParser(sectionID);
-    if (parser != NULL) {
+    if (parser != nullptr) {
         fprintf(stderr, "Running parser: %s\n", parser->name.string());
         status_t err = parser->Parse(STDIN_FILENO, STDOUT_FILENO);
         if (err != NO_ERROR) {
diff --git a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
index eed68b9..21ced9c 100644
--- a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
+++ b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
@@ -109,7 +109,7 @@
             nextToUsage = false;
 
             // NAME is not in the list since we need to modify the end of the CMD index.
-            const char* headerNames[] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD", NULL };
+            const char* headerNames[] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD", nullptr };
             if (!getColumnIndices(columnIndices, headerNames, line)) {
                 return -1;
             }
diff --git a/cmds/incident_helper/src/parsers/PsParser.cpp b/cmds/incident_helper/src/parsers/PsParser.cpp
index 8d64064..d3cb4be 100644
--- a/cmds/incident_helper/src/parsers/PsParser.cpp
+++ b/cmds/incident_helper/src/parsers/PsParser.cpp
@@ -48,7 +48,7 @@
         if (nline++ == 0) {
             header = parseHeader(line, DEFAULT_WHITESPACE);
 
-            const char* headerNames[] = { "LABEL", "USER", "PID", "TID", "PPID", "VSZ", "RSS", "WCHAN", "ADDR", "S", "PRI", "NI", "RTPRIO", "SCH", "PCY", "TIME", "CMD", NULL };
+            const char* headerNames[] = { "LABEL", "USER", "PID", "TID", "PPID", "VSZ", "RSS", "WCHAN", "ADDR", "S", "PRI", "NI", "RTPRIO", "SCH", "PCY", "TIME", "CMD", nullptr };
             if (!getColumnIndices(columnIndices, headerNames, line)) {
                 return -1;
             }
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index ad6f9f1..f74d3bf 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -996,22 +996,6 @@
 Landroid/app/WallpaperManager;->setBitmap(Landroid/graphics/Bitmap;Landroid/graphics/Rect;ZII)I
 Landroid/app/WallpaperManager;->setWallpaperComponent(Landroid/content/ComponentName;I)Z
 Landroid/app/WallpaperManager;->sGlobals:Landroid/app/WallpaperManager$Globals;
-Landroid/appwidget/AppWidgetHost;-><init>(Landroid/content/Context;ILandroid/widget/RemoteViews$OnClickHandler;Landroid/os/Looper;)V
-Landroid/appwidget/AppWidgetHost;->HANDLE_VIEW_DATA_CHANGED:I
-Landroid/appwidget/AppWidgetHost;->mHandler:Landroid/os/Handler;
-Landroid/appwidget/AppWidgetHost;->sService:Lcom/android/internal/appwidget/IAppWidgetService;
-Landroid/appwidget/AppWidgetHostView;->getDefaultPaddingForWidget(Landroid/content/Context;Landroid/content/pm/ApplicationInfo;Landroid/graphics/Rect;)Landroid/graphics/Rect;
-Landroid/appwidget/AppWidgetHostView;->mAppWidgetId:I
-Landroid/appwidget/AppWidgetHostView;->mInfo:Landroid/appwidget/AppWidgetProviderInfo;
-Landroid/appwidget/AppWidgetHostView;->updateAppWidgetSize(Landroid/os/Bundle;IIIIZ)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;Landroid/os/Bundle;)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetIdIfAllowed(IILandroid/content/ComponentName;Landroid/os/Bundle;)Z
-Landroid/appwidget/AppWidgetManager;->bindRemoteViewsService(Landroid/content/Context;ILandroid/content/Intent;Landroid/app/IServiceConnection;I)Z
-Landroid/appwidget/AppWidgetManager;->getInstalledProviders(I)Ljava/util/List;
-Landroid/appwidget/AppWidgetManager;->getInstalledProvidersForProfile(ILandroid/os/UserHandle;Ljava/lang/String;)Ljava/util/List;
-Landroid/appwidget/AppWidgetManager;->mService:Lcom/android/internal/appwidget/IAppWidgetService;
-Landroid/appwidget/AppWidgetProviderInfo;->providerInfo:Landroid/content/pm/ActivityInfo;
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
 Landroid/bluetooth/IBluetooth$Stub;-><init>()V
@@ -2354,10 +2338,6 @@
 Landroid/media/VolumeShaper$State;->mVolume:F
 Landroid/media/VolumeShaper$State;->mXOffset:F
 Landroid/media/WebVttRenderer;-><init>(Landroid/content/Context;)V
-Landroid/mtp/MtpPropertyList;->append(IIIJ)V
-Landroid/mtp/MtpPropertyList;->append(IILjava/lang/String;)V
-Landroid/mtp/MtpStorage;->getPath()Ljava/lang/String;
-Landroid/mtp/MtpStorage;->getStorageId()I
 Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;
 Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String;
 Landroid/net/ConnectivityManager;->EXTRA_AVAILABLE_TETHER:Ljava/lang/String;
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 2fac3eb..23e1202 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -61,15 +61,6 @@
 Landroid/app/VrStateCallback;->onPersistentVrStateChanged(Z)V
 Landroid/app/WallpaperColors;-><init>(Landroid/graphics/Color;Landroid/graphics/Color;Landroid/graphics/Color;I)V
 Landroid/bluetooth/IBluetooth;->sendConnectionStateChange(Landroid/bluetooth/BluetoothDevice;III)V
-Landroid/companion/AssociationRequest;->getDeviceFilters()Ljava/util/List;
-Landroid/companion/AssociationRequest;->isSingleDevice()Z
-Landroid/companion/BluetoothDeviceFilter;->getAddress()Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/net/wifi/ScanResult;)Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceMacAddress(Landroid/os/Parcelable;)Ljava/lang/String;
-Landroid/companion/BluetoothLeDeviceFilter;->getScanFilter()Landroid/bluetooth/le/ScanFilter;
-Landroid/companion/DeviceFilter;->getDeviceDisplayName(Landroid/os/Parcelable;)Ljava/lang/String;
-Landroid/companion/DeviceFilter;->matches(Landroid/os/Parcelable;)Z
 Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 49cc498..f003d4b 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
@@ -53,14 +54,17 @@
     static final int HANDLE_UPDATE = 1;
     static final int HANDLE_PROVIDER_CHANGED = 2;
     static final int HANDLE_PROVIDERS_CHANGED = 3;
+    @UnsupportedAppUsage
     static final int HANDLE_VIEW_DATA_CHANGED = 4;
 
     final static Object sServiceLock = new Object();
+    @UnsupportedAppUsage
     static IAppWidgetService sService;
     static boolean sServiceInitialized = false;
     private DisplayMetrics mDisplayMetrics;
 
     private String mContextOpPackageName;
+    @UnsupportedAppUsage
     private final Handler mHandler;
     private final int mHostId;
     private final Callbacks mCallbacks;
@@ -156,6 +160,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) {
         mContextOpPackageName = context.getOpPackageName();
         mHostId = hostId;
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ab0eb92..a9187b6 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -16,6 +16,7 @@
 
 package android.appwidget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -70,7 +71,9 @@
     Context mContext;
     Context mRemoteContext;
 
+    @UnsupportedAppUsage
     int mAppWidgetId;
+    @UnsupportedAppUsage
     AppWidgetProviderInfo mInfo;
     View mView;
     int mViewMode = VIEW_MODE_NOINIT;
@@ -174,6 +177,7 @@
         return getDefaultPaddingForWidget(context, appInfo, padding);
     }
 
+    @UnsupportedAppUsage
     private static Rect getDefaultPaddingForWidget(Context context, ApplicationInfo appInfo,
             Rect padding) {
         if (padding == null) {
@@ -284,6 +288,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
             int maxHeight, boolean ignorePadding) {
         if (newOptions == null) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 20248b9..dbc1c19 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,6 +23,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.IServiceConnection;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -463,6 +464,7 @@
 
     private final Context mContext;
     private final String mPackageName;
+    @UnsupportedAppUsage
     private final IAppWidgetService mService;
     private final DisplayMetrics mDisplayMetrics;
 
@@ -816,6 +818,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
         if (mService == null) {
             return Collections.emptyList();
@@ -842,6 +845,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
             @Nullable UserHandle profile, @Nullable String packageName) {
         if (mService == null) {
@@ -902,6 +906,7 @@
      *                      provider for this AppWidget.
      * @hide
      */
+    @UnsupportedAppUsage
     public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
         if (mService == null) {
             return;
@@ -924,6 +929,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
         if (mService == null) {
             return;
@@ -1094,6 +1100,7 @@
      * @see Context#getServiceDispatcher(ServiceConnection, Handler, int)
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean bindRemoteViewsService(Context context, int appWidgetId, Intent intent,
             IServiceConnection connection, @Context.BindServiceFlags int flags) {
         if (mService == null) {
@@ -1139,6 +1146,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId,
             ComponentName provider, Bundle options) {
         if (mService == null) {
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 6dd85ca..53315cc 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -270,6 +271,7 @@
     public int widgetFeatures;
 
     /** @hide */
+    @UnsupportedAppUsage
     public ActivityInfo providerInfo;
 
     public AppWidgetProviderInfo() {
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index 922224a..db54f08 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.OneTimeUseBuilder;
@@ -59,12 +60,14 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isSingleDevice() {
         return mSingleDevice;
     }
 
     /** @hide */
     @NonNull
+    @UnsupportedAppUsage
     public List<DeviceFilter<?>> getDeviceFilters() {
         return mDeviceFilters;
     }
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index 84e1536..7507e17 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -25,6 +25,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
 import android.os.Parcel;
 import android.os.ParcelUuid;
@@ -99,6 +100,7 @@
 
     /** @hide */
     @Nullable
+    @UnsupportedAppUsage
     public String getAddress() {
         return mAddress;
     }
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 4ee38fe..bd507a6 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.le.ScanFilter;
 import android.net.wifi.ScanResult;
@@ -124,14 +125,17 @@
         Log.i(LOG_TAG, getDeviceDisplayNameInternal(device) + (result ? " ~ " : " !~ ") + criteria);
     }
 
+    @UnsupportedAppUsage
     public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) {
         return firstNotEmpty(device.getAliasName(), device.getAddress());
     }
 
+    @UnsupportedAppUsage
     public static String getDeviceDisplayNameInternal(@NonNull ScanResult device) {
         return firstNotEmpty(device.SSID, device.BSSID);
     }
 
+    @UnsupportedAppUsage
     public static String getDeviceMacAddress(@NonNull Parcelable device) {
         if (device instanceof BluetoothDevice) {
             return ((BluetoothDevice) device).getAddress();
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index 7fb768c..1de931e 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -25,6 +25,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.le.ScanFilter;
 import android.bluetooth.le.ScanRecord;
@@ -92,6 +93,7 @@
 
     /** @hide */
     @NonNull
+    @UnsupportedAppUsage
     public ScanFilter getScanFilter() {
         return mScanFilter;
     }
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
index 10135a4..dc7cf82 100644
--- a/core/java/android/companion/DeviceFilter.java
+++ b/core/java/android/companion/DeviceFilter.java
@@ -19,6 +19,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 
 import java.lang.annotation.Retention;
@@ -44,9 +45,11 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     boolean matches(D device);
 
     /** @hide */
+    @UnsupportedAppUsage
     String getDeviceDisplayName(D device);
 
     /**  @hide */
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 52a2354..e6b3fa8 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -372,7 +372,7 @@
         if (score < 0) {
             throw new IllegalArgumentException("Score must be >= 0");
         }
-        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
+        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED,  score, 0);
     }
 
     /**
@@ -387,7 +387,7 @@
      * {@link #saveAcceptUnvalidated} to respect the user's choice.
      */
     public void explicitlySelected(boolean acceptUnvalidated) {
-        queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, acceptUnvalidated);
+        queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, acceptUnvalidated ? 1 : 0, 0);
     }
 
     /**
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 405651e..6a5bb1c 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -232,6 +232,14 @@
      * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jstring)] is out of range
      */
     public native final void putString(long offset, String x);
+    /**
+     * Writes a native handle (without duplicating the underlying file descriptors) at an offset.
+     *
+     * @param offset location to write value
+     * @param x a {@link NativeHandle} instance to write
+     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
+     */
+    public native final void putNativeHandle(long offset, NativeHandle x);
 
     /**
      * Put a boolean array contiguously at an offset in the blob.
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 0eb62c95..7a51db2 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -115,6 +115,13 @@
      * @param val to write
      */
     public native final void writeString(String val);
+    /**
+     * Writes a native handle (without duplicating the underlying
+     * file descriptors) to the end of the parcel.
+     *
+     * @param val to write
+     */
+    public native final void writeNativeHandle(NativeHandle val);
 
     /**
      * Writes an array of boolean values to the end of the parcel.
@@ -159,6 +166,11 @@
      * @param val to write
      */
     private native final void writeStringVector(String[] val);
+    /**
+     * Writes an array of native handles to the end of the parcel.
+     * @param val array of {@link NativeHandle} objects to write
+     */
+    private native final void writeNativeHandleVector(NativeHandle[] val);
 
     /**
      * Helper method to write a list of Booleans to val.
@@ -267,6 +279,14 @@
     }
 
     /**
+     * Helper method to write a list of native handles to the end of the parcel.
+     * @param val list of {@link NativeHandle} objects to write
+     */
+    public final void writeNativeHandleVector(ArrayList<NativeHandle> val) {
+        writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
+    }
+
+    /**
      * Write a hwbinder object to the end of the parcel.
      * @param binder value to write
      */
@@ -328,6 +348,30 @@
      * @throws IllegalArgumentException if the parcel has no more data
      */
     public native final String readString();
+    /**
+     * Reads a native handle (without duplicating the underlying file
+     * descriptors) from the parcel. These file descriptors will only
+     * be open for the duration that the binder window is open. If they
+     * are needed further, you must call {@link NativeHandle#dup()}.
+     *
+     * @return a {@link NativeHandle} instance parsed from the parcel
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    public native final NativeHandle readNativeHandle();
+    /**
+     * Reads an embedded native handle (without duplicating the underlying
+     * file descriptors) from the parcel. These file descriptors will only
+     * be open for the duration that the binder window is open. If they
+     * are needed further, you must call {@link NativeHandle#dup()}. You
+     * do not need to call close on the NativeHandle returned from this.
+     *
+     * @param parentHandle handle from which to read the embedded object
+     * @param offset offset into parent
+     * @return a {@link NativeHandle} instance parsed from the parcel
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    public native final NativeHandle readEmbeddedNativeHandle(
+            long parentHandle, long offset);
 
     /**
      * Reads an array of boolean values from the parcel.
@@ -377,6 +421,12 @@
      * @throws IllegalArgumentException if the parcel has no more data
      */
     private native final String[] readStringVectorAsArray();
+    /**
+     * Reads an array of native handles from the parcel.
+     * @return array of {@link NativeHandle} objects
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    private native final NativeHandle[] readNativeHandleAsArray();
 
     /**
      * Convenience method to read a Boolean vector as an ArrayList.
@@ -465,6 +515,15 @@
     }
 
     /**
+     * Convenience method to read a vector of native handles as an ArrayList.
+     * @return array of {@link NativeHandle} objects.
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    public final ArrayList<NativeHandle> readNativeHandleVector() {
+        return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
+    }
+
+    /**
      * Reads a strong binder value from the parcel.
      * @return binder object read from parcel or null if no binder can be read
      * @throws IllegalArgumentException if the parcel has no more data
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 31dbafa..20ca19b 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -372,11 +372,6 @@
     void stopClatd(String interfaceName);
 
     /**
-     * Determine whether the clatd (464xlat) service has been started on the given interface.
-     */
-    boolean isClatdStarted(String interfaceName);
-
-    /**
      * Start listening for mobile activity state changes.
      */
     void registerNetworkActivityListener(INetworkActivityListener listener);
diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java
new file mode 100644
index 0000000..fbecc8e
--- /dev/null
+++ b/core/java/android/os/NativeHandle.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import java.io.Closeable;
+import java.io.FileDescriptor;
+
+/**
+ * Collection representing a set of open file descriptors and an opaque data stream.
+ *
+ * @hide
+ */
+@SystemApi
+public final class NativeHandle implements Closeable {
+    // whether this object owns mFds
+    private boolean mOwn = false;
+    private FileDescriptor[] mFds;
+    private int[] mInts;
+
+    /**
+     * Constructs a {@link NativeHandle} object containing
+     * zero file descriptors and an empty data stream.
+     */
+    public NativeHandle() {
+        this(new FileDescriptor[0], new int[0], false);
+    }
+
+    /**
+     * Constructs a {@link NativeHandle} object containing the given
+     * {@link FileDescriptor} object and an empty data stream.
+     */
+    public NativeHandle(@NonNull FileDescriptor descriptor, boolean own) {
+        this(new FileDescriptor[] {descriptor}, new int[0], own);
+    }
+
+    /**
+     * Convenience method for creating a list of file descriptors.
+     *
+     * @hide
+     */
+    private static FileDescriptor[] createFileDescriptorArray(@NonNull int[] fds) {
+        FileDescriptor[] list = new FileDescriptor[fds.length];
+        for (int i = 0; i < fds.length; i++) {
+            FileDescriptor descriptor = new FileDescriptor();
+            descriptor.setInt$(fds[i]);
+            list[i] = descriptor;
+        }
+        return list;
+    }
+
+    /**
+     * Convenience method for instantiating a {@link NativeHandle} from JNI. It does
+     * not take ownership of the int[] params. It does not dupe the FileDescriptors.
+     *
+     * @hide
+     */
+    private NativeHandle(@NonNull int[] fds, @NonNull int[] ints, boolean own) {
+        this(createFileDescriptorArray(fds), ints, own);
+    }
+
+    /**
+     * Instantiate an opaque {@link NativeHandle} from fds and integers.
+     *
+     * @param own whether the fds are owned by this object and should be closed
+     */
+    public NativeHandle(@NonNull FileDescriptor[] fds, @NonNull int[] ints, boolean own) {
+        mFds = fds.clone();
+        mInts = ints.clone();
+        mOwn = own;
+    }
+
+    /**
+     * Returns whether this {@link NativeHandle} object contains a single file
+     * descriptor and nothing else.
+     *
+     * @return a boolean value
+     */
+    public boolean hasSingleFileDescriptor() {
+        return mFds.length == 1 && mInts.length == 0;
+    }
+
+    /**
+     * Explicitly duplicate NativeHandle (this dups all file descritptors).
+     *
+     * If this method is called, this must also be explicitly closed with
+     * {@link #close()}.
+     */
+    public NativeHandle dup() throws java.io.IOException {
+        FileDescriptor[] fds = new FileDescriptor[mFds.length];
+        try {
+            for (int i = 0; i < mFds.length; i++) {
+                fds[i] = Os.dup(mFds[i]);
+            }
+        } catch (ErrnoException e) {
+            e.rethrowAsIOException();
+        }
+        return new NativeHandle(fds, mInts, true /*own*/);
+    }
+
+    /**
+     * Closes the file descriptors if they are owned by this object.
+     *
+     * This also invalidates the object.
+     */
+    @Override
+    public void close() throws java.io.IOException {
+        if (!mOwn) {
+            return;
+        }
+
+        try {
+            for (FileDescriptor fd : mFds) {
+                Os.close(fd);
+            }
+        } catch (ErrnoException e) {
+            e.rethrowAsIOException();
+        }
+
+        mOwn = false;
+        mFds = null;
+        mInts = null;
+    }
+
+    /**
+     * Returns the underlying lone file descriptor.
+     *
+     * @return a {@link FileDescriptor} object
+     * @throws IllegalStateException if this object contains either zero or
+     *         more than one file descriptor, or a non-empty data stream.
+     */
+    public FileDescriptor getFileDescriptor() {
+        if (!hasSingleFileDescriptor()) {
+            throw new IllegalStateException(
+                    "NativeHandle is not single file descriptor. Contents must"
+                    + " be retreived through getFileDescriptors and getInts.");
+        }
+
+        return mFds[0];
+    }
+
+    /**
+     * Convenience method for fetching this object's file descriptors from JNI.
+     * @return a mutable copy of the underlying file descriptors (as an int[])
+     *
+     * @hide
+     */
+    private int[] getFdsAsIntArray() {
+        int numFds = mFds.length;
+        int[] fds = new int[numFds];
+
+        for (int i = 0; i < numFds; i++) {
+            fds[i] = mFds[i].getInt$();
+        }
+
+        return fds;
+    }
+
+    /**
+     * Fetch file descriptors.
+     *
+     * @return the fds.
+     */
+    public FileDescriptor[] getFileDescriptors() {
+        return mFds;
+    }
+
+    /**
+     * Fetch opaque ints. Note: This object retains ownership of the data.
+     *
+     * @return the opaque data stream.
+     */
+    public int[] getInts() {
+        return mInts;
+    }
+}
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index bf33519..d5bec0f 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -20,9 +20,10 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 
-import libcore.io.IoUtils;
 import dalvik.system.CloseGuard;
 
+import libcore.io.IoUtils;
+
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.UUID;
@@ -56,7 +57,7 @@
 
     private final boolean mIsOwner;
     private final long mMemoryAddr;
-    private int mFd = -1;
+    private ParcelFileDescriptor mFd;
 
     /**
      * Creates a new instance.
@@ -71,8 +72,8 @@
         }
         mIsOwner = true;
         final String name = UUID.randomUUID().toString();
-        mFd = nativeCreate(name, size);
-        mMemoryAddr = nativeOpen(mFd, mIsOwner);
+        mFd = ParcelFileDescriptor.adoptFd(nativeCreate(name, size));
+        mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
         mCloseGuard.open("close");
     }
 
@@ -82,8 +83,8 @@
         if (pfd == null) {
             throw new IOException("No backing file descriptor");
         }
-        mFd = pfd.detachFd();
-        mMemoryAddr = nativeOpen(mFd, mIsOwner);
+        mFd = ParcelFileDescriptor.adoptFd(pfd.detachFd());
+        mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
         mCloseGuard.open("close");
     }
 
@@ -105,7 +106,7 @@
     public int get(int index) throws IOException {
         enforceNotClosed();
         enforceValidIndex(index);
-        return nativeGet(mFd, mMemoryAddr, index);
+        return nativeGet(mFd.getFd(), mMemoryAddr, index);
     }
 
     /**
@@ -121,7 +122,7 @@
         enforceNotClosed();
         enforceWritable();
         enforceValidIndex(index);
-        nativeSet(mFd, mMemoryAddr, index, value);
+        nativeSet(mFd.getFd(), mMemoryAddr, index, value);
     }
 
     /**
@@ -131,7 +132,7 @@
      */
     public int size() throws IOException {
         enforceNotClosed();
-        return nativeSize(mFd);
+        return nativeSize(mFd.getFd());
     }
 
     /**
@@ -142,8 +143,9 @@
     @Override
     public void close() throws IOException {
         if (!isClosed()) {
-            nativeClose(mFd, mMemoryAddr, mIsOwner);
-            mFd = -1;
+            nativeClose(mFd.getFd(), mMemoryAddr, mIsOwner);
+            mFd.close();
+            mFd = null;
             mCloseGuard.close();
         }
     }
@@ -152,7 +154,7 @@
      * @return Whether this array is closed and shouldn't be used.
      */
     public boolean isClosed() {
-        return mFd == -1;
+        return mFd == null;
     }
 
     @Override
@@ -175,13 +177,8 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
-        try {
-            // Don't let writing to a parcel to close our fd - plz
-            parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } finally {
-            pfd.detachFd();
-        }
+        // Don't let writing to a parcel to close our fd - plz
+        parcel.writeParcelable(mFd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
     }
 
     @Override
@@ -195,13 +192,13 @@
         if (getClass() != obj.getClass()) {
             return false;
         }
-        MemoryIntArray other = (MemoryIntArray) obj;
-        return mFd == other.mFd;
+
+        return false;
     }
 
     @Override
     public int hashCode() {
-        return mFd;
+        return mFd.hashCode();
     }
 
     private void enforceNotClosed() {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 88ffb3f..494a957 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -93,6 +93,7 @@
         "android_os_HwBlob.cpp",
         "android_os_HwParcel.cpp",
         "android_os_HwRemoteBinder.cpp",
+        "android_os_NativeHandle.cpp",
         "android_os_MemoryFile.cpp",
         "android_os_MessageQueue.cpp",
         "android_os_Parcel.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d059253..f7f10c4 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -165,6 +165,7 @@
 extern int register_android_os_HwBlob(JNIEnv *env);
 extern int register_android_os_HwParcel(JNIEnv *env);
 extern int register_android_os_HwRemoteBinder(JNIEnv *env);
+extern int register_android_os_NativeHandle(JNIEnv *env);
 extern int register_android_os_MessageQueue(JNIEnv* env);
 extern int register_android_os_Parcel(JNIEnv* env);
 extern int register_android_os_SELinux(JNIEnv* env);
@@ -1345,6 +1346,7 @@
     REG_JNI(register_android_os_HwBlob),
     REG_JNI(register_android_os_HwParcel),
     REG_JNI(register_android_os_HwRemoteBinder),
+    REG_JNI(register_android_os_NativeHandle),
     REG_JNI(register_android_os_VintfObject),
     REG_JNI(register_android_os_VintfRuntimeInfo),
     REG_JNI(register_android_nio_utils),
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index bb916d2..cb55618 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -21,6 +21,7 @@
 #include "android_os_HwBlob.h"
 
 #include "android_os_HwParcel.h"
+#include "android_os_NativeHandle.h"
 
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
@@ -31,6 +32,7 @@
 #include "core_jni_helpers.h"
 
 using android::AndroidRuntime;
+using android::hardware::hidl_handle;
 using android::hardware::hidl_string;
 
 #define PACKAGE_PATH    "android/os"
@@ -82,6 +84,7 @@
 JHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size)
     : mBuffer(nullptr),
       mSize(size),
+      mType(BlobType::GENERIC),
       mOwnsBuffer(true),
       mHandle(0) {
     if (size > 0) {
@@ -159,6 +162,15 @@
     return mSize;
 }
 
+void JHwBlob::specializeBlobTo(BlobType type) {
+    CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
+    mType = type;
+}
+
+JHwBlob::BlobType JHwBlob::type() const {
+    return mType;
+}
+
 status_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) {
     size_t index = mSubBlobs.add();
     BlobInfo *info = &mSubBlobs.editItemAt(index);
@@ -172,42 +184,52 @@
 }
 
 status_t JHwBlob::writeToParcel(hardware::Parcel *parcel) const {
-    size_t handle;
+    CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
+
+    size_t handle = 0;
     status_t err = parcel->writeBuffer(data(), size(), &handle);
 
     if (err != OK) {
         return err;
     }
 
-    for (size_t i = 0; i < mSubBlobs.size(); ++i) {
-        const BlobInfo &info = mSubBlobs[i];
-
-        err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
-
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    return OK;
+    return writeSubBlobsToParcel(parcel, handle);
 }
 
 status_t JHwBlob::writeEmbeddedToParcel(
         hardware::Parcel *parcel,
         size_t parentHandle,
         size_t parentOffset) const {
-    size_t handle;
-    status_t err = parcel->writeEmbeddedBuffer(
-            data(), size(), &handle, parentHandle, parentOffset);
+    size_t handle = 0;
+    status_t err = OK;
+
+    switch (mType) {
+        case BlobType::GENERIC: {
+            err = parcel->writeEmbeddedBuffer(data(), size(), &handle, parentHandle, parentOffset);
+            break;
+        }
+        case BlobType::NATIVE_HANDLE: {
+            err = parcel->writeEmbeddedNativeHandle(
+                    static_cast<const native_handle *>(data()), parentHandle, parentOffset);
+
+            CHECK(mSubBlobs.empty());
+            break;
+        }
+        default: { err = INVALID_OPERATION; }
+    }
 
     if (err != OK) {
         return err;
     }
 
+    return writeSubBlobsToParcel(parcel, handle);
+}
+
+status_t JHwBlob::writeSubBlobsToParcel(hardware::Parcel *parcel,
+        size_t parentHandle) const {
     for (size_t i = 0; i < mSubBlobs.size(); ++i) {
         const BlobInfo &info = mSubBlobs[i];
-
-        err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
+        status_t err = info.mBlob->writeEmbeddedToParcel(parcel, parentHandle, info.mOffset);
 
         if (err != OK) {
             return err;
@@ -252,7 +274,7 @@
     }
 }
 
-static jlong JHwBlob_native_init(JNIEnv *env) {
+static jlong JHwBlob_native_init(JNIEnv *env, jclass /*clazz*/) {
     JHwBlob::InitClass(env);
 
     return reinterpret_cast<jlong>(&releaseNativeContext);
@@ -456,6 +478,31 @@
     blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob);
 }
 
+static void JHwBlob_native_putNativeHandle(JNIEnv *env, jobject thiz,
+        jlong offset, jobject jHandle) {
+    std::unique_ptr<native_handle_t, int(*)(native_handle_t*)> nativeHandle(
+            JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */),
+            native_handle_delete);
+
+    size_t size = 0;
+    if (nativeHandle != nullptr) {
+        size = sizeof(native_handle_t) + nativeHandle->numFds * sizeof(int)
+               + nativeHandle->numInts * sizeof(int);
+    }
+
+    ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
+    sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
+    subBlob->specializeBlobTo(JHwBlob::BlobType::NATIVE_HANDLE);
+    subBlob->write(0 /* offset */, nativeHandle.get(), size);
+
+    hidl_handle cppHandle;
+    cppHandle.setTo(static_cast<native_handle_t *>(subBlob->data()), false /* shouldOwn */);
+
+    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+    blob->write(offset, &cppHandle, sizeof(cppHandle));
+    blob->putBlob(offset + hidl_handle::kOffsetOfNativeHandle, subBlob);
+}
+
 #define DEFINE_BLOB_ARRAY_PUTTER(Suffix,Type,NewType)                          \
 static void JHwBlob_native_put ## Suffix ## Array(                             \
         JNIEnv *env, jobject thiz, jlong offset, Type ## Array array) {        \
@@ -563,6 +610,8 @@
     { "putFloat", "(JF)V", (void *)JHwBlob_native_putFloat },
     { "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble },
     { "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString },
+    { "putNativeHandle", "(JL" PACKAGE_PATH "/NativeHandle;)V",
+        (void*)JHwBlob_native_putNativeHandle },
 
     { "putBoolArray", "(J[Z)V", (void *)JHwBlob_native_putBoolArray },
     { "putInt8Array", "(J[B)V", (void *)JHwBlob_native_putInt8Array },
diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h
index 6b1db63..69a1b16 100644
--- a/core/jni/android_os_HwBlob.h
+++ b/core/jni/android_os_HwBlob.h
@@ -27,6 +27,11 @@
 namespace android {
 
 struct JHwBlob : public RefBase {
+    enum class BlobType {
+        GENERIC,
+        NATIVE_HANDLE,
+    };
+
     static void InitClass(JNIEnv *env);
 
     static sp<JHwBlob> SetNativeContext(
@@ -54,6 +59,9 @@
 
     size_t size() const;
 
+    void specializeBlobTo(BlobType type);
+    BlobType type() const;
+
     status_t putBlob(size_t offset, const sp<JHwBlob> &blob);
 
     status_t writeToParcel(hardware::Parcel *parcel) const;
@@ -74,12 +82,15 @@
 
     void *mBuffer;
     size_t mSize;
+    BlobType mType;
     bool mOwnsBuffer;
 
     size_t mHandle;
 
     Vector<BlobInfo> mSubBlobs;
 
+    status_t writeSubBlobsToParcel(hardware::Parcel *parcel, size_t parentHandle) const;
+
     DISALLOW_COPY_AND_ASSIGN(JHwBlob);
 };
 
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 061349a..7221ca1 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -22,6 +22,7 @@
 
 #include "android_os_HwBinder.h"
 #include "android_os_HwBlob.h"
+#include "android_os_NativeHandle.h"
 #include "android_os_HwRemoteBinder.h"
 
 #include <nativehelper/JNIHelp.h>
@@ -34,6 +35,7 @@
 
 using android::AndroidRuntime;
 
+using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 
@@ -436,6 +438,18 @@
     signalExceptionForError(env, err);
 }
 
+static void JHwParcel_native_writeNativeHandle(JNIEnv *env, jobject thiz, jobject valObj) {
+    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+
+    EphemeralStorage *storage = impl->getStorage();
+    native_handle_t *handle = JNativeHandle::MakeCppNativeHandle(env, valObj, storage);
+
+    hardware::Parcel *parcel = impl->getParcel();
+    status_t err = parcel->writeNativeHandleNoDup(handle);
+
+    signalExceptionForError(env, err);
+}
+
 #define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type)                               \
 static void JHwParcel_native_write ## Suffix ## Vector(                        \
         JNIEnv *env, jobject thiz, Type ## Array valObj) {                     \
@@ -524,12 +538,96 @@
     signalExceptionForError(env, err);
 }
 
+template<typename T>
+static void WriteHidlVector(JNIEnv *env, jobject thiz, const hidl_vec<T> &vec) {
+    hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+    size_t parentHandle;
+    status_t err = parcel->writeBuffer(&vec, sizeof(vec), &parentHandle);
+
+    if (err == OK) {
+        size_t childHandle;
+        err = ::android::hardware::writeEmbeddedToParcel(
+                vec,
+                parcel,
+                parentHandle,
+                0 /* parentOffset */,
+                &childHandle);
+
+        for (size_t i = 0; (err == OK) && (i < vec.size()); ++i) {
+            err = ::android::hardware::writeEmbeddedToParcel(
+                    vec[i],
+                    parcel,
+                    childHandle,
+                    i * sizeof(T));
+        }
+    }
+
+    signalExceptionForError(env, err);
+}
+
+static void JHwParcel_native_writeStringVector(
+        JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
+    if (arrayObj == nullptr) {
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);
+        return;
+    }
+
+    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+    EphemeralStorage *storage = impl->getStorage();
+
+    void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_string>));
+    hidl_vec<hidl_string> *vec = new (vecPtr) hidl_vec<hidl_string>();
+
+    jsize len = env->GetArrayLength(arrayObj);
+    hidl_string *strings = storage->allocStringArray(len);
+    vec->setToExternal(strings, len, false /* shouldOwn */);
+
+    for (jsize i = 0; i < len; ++i) {
+        ScopedLocalRef<jstring> stringObj(env, (jstring) env->GetObjectArrayElement(arrayObj, i));
+
+        const hidl_string *s = storage->allocTemporaryString(env, stringObj.get());
+        strings[i].setToExternal(s->c_str(), s->size());
+    }
+
+    WriteHidlVector(env, thiz, *vec);
+}
+
+static void JHwParcel_native_writeNativeHandleVector(
+        JNIEnv *env, jobject thiz, jobjectArray jHandleArray) {
+    if (jHandleArray == nullptr) {
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);
+        return;
+    }
+
+    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+    EphemeralStorage *storage = impl->getStorage();
+
+    void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_handle>));
+    hidl_vec<hidl_handle> *vec = new (vecPtr) hidl_vec<hidl_handle>();
+
+    jsize len = env->GetArrayLength(jHandleArray);
+    hidl_handle *handles = static_cast<hidl_handle *>(
+            storage->allocTemporaryStorage(len * sizeof(hidl_handle)));
+
+    vec->setToExternal(handles, len, false /* shouldOwn */);
+    for (jsize i = 0; i < len; i++) {
+        ScopedLocalRef<jobject> jHandle(env, env->GetObjectArrayElement(jHandleArray, i));
+
+        native_handle_t* handle = JNativeHandle::MakeCppNativeHandle(env, jHandle.get(), storage);
+
+        new (&(handles[i])) hidl_handle();
+        handles[i].setTo(handle, false /* shouldOwn */);
+    }
+
+    WriteHidlVector(env, thiz, *vec);
+}
+
 static void JHwParcel_native_writeStrongBinder(
         JNIEnv *env, jobject thiz, jobject binderObj) {
     sp<hardware::IBinder> binder;
     if (binderObj != NULL) {
-        ScopedLocalRef<jclass> hwBinderKlass(
-                env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
+        ScopedLocalRef<jclass> hwBinderKlass(env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
 
         ScopedLocalRef<jclass> hwRemoteBinderKlass(
                 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
@@ -587,6 +685,37 @@
     return MakeStringObjFromHidlString(env, *s);
 }
 
+static jobject ReadNativeHandle(JNIEnv *env, jobject thiz, jboolean embedded,
+        jlong parentHandle, jlong offset) {
+    hardware::Parcel *parcel =
+            JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+    const native_handle_t *handle = nullptr;
+    status_t err = OK;
+
+    if (embedded) {
+        err = parcel->readNullableEmbeddedNativeHandle(parentHandle, offset, &handle);
+    } else {
+        err = parcel->readNullableNativeHandleNoDup(&handle);
+    }
+
+    if (err != OK) {
+        signalExceptionForError(env, err);
+        return nullptr;
+    }
+
+    return JNativeHandle::MakeJavaNativeHandleObj(env, handle);
+}
+
+static jobject JHwParcel_native_readNativeHandle(JNIEnv *env, jobject thiz) {
+    return ReadNativeHandle(env, thiz, false /*embedded*/, 0L /*parentHandle*/, 0L /*offset*/);
+}
+
+static jobject JHwParcel_native_readEmbeddedNativeHandle(
+        JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
+    return ReadNativeHandle(env, thiz, true /*embedded*/, parentHandle, offset);
+}
+
 #define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType)                       \
 static Type ## Array JHwParcel_native_read ## Suffix ## Vector(                \
         JNIEnv *env, jobject thiz) {                                           \
@@ -630,10 +759,8 @@
 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
 
-static jbooleanArray JHwParcel_native_readBoolVector(
-        JNIEnv *env, jobject thiz) {
-    hardware::Parcel *parcel =
-        JHwParcel::GetNativeContext(env, thiz)->getParcel();
+static jbooleanArray JHwParcel_native_readBoolVector(JNIEnv *env, jobject thiz) {
+    hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
     size_t parentHandle;
 
@@ -692,101 +819,62 @@
     return arrayObj;
 }
 
-static jobjectArray JHwParcel_native_readStringVector(
-        JNIEnv *env, jobject thiz) {
-    typedef hidl_vec<hidl_string> string_vec;
+template<typename T>
+static const hidl_vec<T> *ReadHidlVector(JNIEnv *env, jobject thiz) {
+    const hidl_vec<T> *vec;
 
-    hardware::Parcel *parcel =
-        JHwParcel::GetNativeContext(env, thiz)->getParcel();
+    hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
     size_t parentHandle;
-
-    const string_vec *vec;
-    status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
-            reinterpret_cast<const void **>(&vec));
-
-    if (err != OK) {
-        signalExceptionForError(env, err);
-        return NULL;
-    }
-
-    size_t childHandle;
-    err = ::android::hardware::readEmbeddedFromParcel(
-            const_cast<string_vec &>(*vec),
-            *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
-
-    for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
-        err = android::hardware::readEmbeddedFromParcel(
-                    const_cast<hidl_string &>((*vec)[i]),
-                    *parcel,
-                    childHandle,
-                    i * sizeof(hidl_string) /* parentOffset */);
-    }
-
-    if (err != OK) {
-        signalExceptionForError(env, err);
-        return NULL;
-    }
-
-    return MakeStringArray(env, &(*vec)[0], vec->size());
-}
-
-static void JHwParcel_native_writeStringVector(
-        JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
-    typedef hidl_vec<hidl_string> string_vec;
-
-    if (arrayObj == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-        return;
-    }
-
-    jsize len = env->GetArrayLength(arrayObj);
-
-    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
-
-    void *vecPtr =
-        impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
-
-    string_vec *vec = new (vecPtr) string_vec;
-
-    hidl_string *strings = impl->getStorage()->allocStringArray(len);
-    vec->setToExternal(strings, len);
-
-    for (jsize i = 0; i < len; ++i) {
-        ScopedLocalRef<jstring> stringObj(
-                env,
-                (jstring)env->GetObjectArrayElement(arrayObj, i));
-
-        const hidl_string *s =
-            impl->getStorage()->allocTemporaryString(env, stringObj.get());
-
-        strings[i].setToExternal(s->c_str(), s->size());
-    }
-
-    hardware::Parcel *parcel = impl->getParcel();
-
-    size_t parentHandle;
-    status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
+    status_t err = parcel->readBuffer(sizeof(hidl_vec<T>),
+            &parentHandle, reinterpret_cast<const void **>(&vec));
 
     if (err == OK) {
         size_t childHandle;
-        err = ::android::hardware::writeEmbeddedToParcel(
-                *vec,
-                parcel,
-                parentHandle,
+        err = ::android::hardware::readEmbeddedFromParcel(
+                const_cast<hidl_vec<T> &>(*vec),
+                *parcel, parentHandle,
                 0 /* parentOffset */,
                 &childHandle);
 
-        for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
-            err = ::android::hardware::writeEmbeddedToParcel(
-                    (*vec)[i],
-                    parcel,
+        for (size_t i = 0; (err == OK) && (i < vec->size()); i++) {
+            err = android::hardware::readEmbeddedFromParcel(
+                    const_cast<T &>((*vec)[i]),
+                    *parcel,
                     childHandle,
-                    i * sizeof(hidl_string));
+                    i * sizeof(T) /* parentOffset */);
         }
     }
 
-    signalExceptionForError(env, err);
+    if (err != OK) {
+        signalExceptionForError(env, err);
+        return nullptr;
+    }
+
+    return vec;
+}
+
+static jobjectArray JHwParcel_native_readStringVector(
+        JNIEnv *env, jobject thiz) {
+    const hidl_vec<hidl_string> *vec = ReadHidlVector<hidl_string>(env, thiz);
+    return MakeStringArray(env, &(*vec)[0], vec->size());
+}
+
+static jobjectArray JHwParcel_native_readNativeHandleVector(
+        JNIEnv *env, jobject thiz) {
+    const hidl_vec<hidl_handle> *vec = ReadHidlVector<hidl_handle>(env, thiz);
+
+    jsize length = vec->size();
+    jobjectArray objArray = JNativeHandle::AllocJavaNativeHandleObjArray(
+            env, length);
+
+    for (jsize i = 0; i < length; i++) {
+        jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, (*vec)[i].getNativeHandle());
+
+        env->SetObjectArrayElement(objArray, i, jHandle);
+    }
+
+    return objArray;
 }
 
 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
@@ -890,6 +978,9 @@
     { "writeString", "(Ljava/lang/String;)V",
         (void *)JHwParcel_native_writeString },
 
+    { "writeNativeHandle", "(L" PACKAGE_PATH "/NativeHandle;)V",
+        (void *)JHwParcel_native_writeNativeHandle },
+
     { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
     { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
     { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
@@ -903,6 +994,9 @@
     { "writeStringVector", "([Ljava/lang/String;)V",
         (void *)JHwParcel_native_writeStringVector },
 
+    { "writeNativeHandleVector", "([L" PACKAGE_PATH "/NativeHandle;)V",
+        (void *)JHwParcel_native_writeNativeHandleVector },
+
     { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
         (void *)JHwParcel_native_writeStrongBinder },
 
@@ -920,6 +1014,12 @@
     { "readString", "()Ljava/lang/String;",
         (void *)JHwParcel_native_readString },
 
+    { "readNativeHandle", "()L" PACKAGE_PATH "/NativeHandle;",
+        (void *)JHwParcel_native_readNativeHandle },
+
+    { "readEmbeddedNativeHandle", "(JJ)L" PACKAGE_PATH "/NativeHandle;",
+        (void *)JHwParcel_native_readEmbeddedNativeHandle },
+
     { "readBoolVectorAsArray", "()[Z",
         (void *)JHwParcel_native_readBoolVector },
 
@@ -944,6 +1044,9 @@
     { "readStringVectorAsArray", "()[Ljava/lang/String;",
         (void *)JHwParcel_native_readStringVector },
 
+    { "readNativeHandleAsArray", "()[L" PACKAGE_PATH "/NativeHandle;",
+        (void *)JHwParcel_native_readNativeHandleVector },
+
     { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
         (void *)JHwParcel_native_readStrongBinder },
 
diff --git a/core/jni/android_os_NativeHandle.cpp b/core/jni/android_os_NativeHandle.cpp
new file mode 100644
index 0000000..770fdb0
--- /dev/null
+++ b/core/jni/android_os_NativeHandle.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android_os_NativeHandle.h"
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+#include "core_jni_helpers.h"
+
+#define PACKAGE_PATH    "android/os"
+#define CLASS_NAME      "NativeHandle"
+#define CLASS_PATH      PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+static struct {
+    jclass clazz;
+    jmethodID constructID;  // NativeHandle(int[] fds, int[] ints, boolean owns)
+
+    jmethodID getFdsID;  // int[] NativeHandle.getFds()
+    jmethodID getIntsID;  // int[] NativeHandle.getInts()
+} gNativeHandleFields;
+
+jobject JNativeHandle::MakeJavaNativeHandleObj(
+        JNIEnv *env, const native_handle_t *handle) {
+    if (handle == nullptr) { return nullptr; }
+
+    const int numFds = handle->numFds;
+    ScopedLocalRef<jintArray> fds(env, env->NewIntArray(numFds));
+    env->SetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0]));
+
+    const int numInts = handle->numInts;
+    ScopedLocalRef<jintArray> ints(env, env->NewIntArray(numInts));
+    env->SetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds]));
+
+    return env->NewObject(gNativeHandleFields.clazz,
+            gNativeHandleFields.constructID, fds.get(), ints.get(), false /*own*/);
+}
+
+native_handle_t *JNativeHandle::MakeCppNativeHandle(
+        JNIEnv *env, jobject jHandle, EphemeralStorage *storage) {
+    if (jHandle == nullptr) { return nullptr; }
+
+    if (!env->IsInstanceOf(jHandle, gNativeHandleFields.clazz)) {
+        jniThrowException(env, "java/lang/ClassCastException",
+                "jHandle must be an instance of NativeHandle.");
+        return nullptr;
+    }
+
+    ScopedLocalRef<jintArray> fds(env, (jintArray) env->CallObjectMethod(
+            jHandle, gNativeHandleFields.getFdsID));
+
+    ScopedLocalRef<jintArray> ints(env, (jintArray) env->CallObjectMethod(
+            jHandle, gNativeHandleFields.getIntsID));
+
+    const int numFds = (int) env->GetArrayLength(fds.get());
+    const int numInts = (int) env->GetArrayLength(ints.get());
+
+    native_handle_t *handle = (storage == nullptr)
+            ? native_handle_create(numFds, numInts)
+            : storage->allocTemporaryNativeHandle(numFds, numInts);
+
+    if (handle != nullptr) {
+        env->GetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0]));
+        env->GetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds]));
+    } else {
+        jniThrowException(env, "java/lang/OutOfMemoryError",
+                "Failed to allocate memory for native_handle_t.");
+    }
+
+    return handle;
+}
+
+jobjectArray JNativeHandle::AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length) {
+    return env->NewObjectArray(length, gNativeHandleFields.clazz, nullptr);
+}
+
+int register_android_os_NativeHandle(JNIEnv *env) {
+    jclass clazz = FindClassOrDie(env, CLASS_PATH);
+    gNativeHandleFields.clazz = MakeGlobalRefOrDie(env, clazz);
+
+    gNativeHandleFields.constructID = GetMethodIDOrDie(env, clazz, "<init>", "([I[IZ)V");
+    gNativeHandleFields.getFdsID = GetMethodIDOrDie(env, clazz, "getFdsAsIntArray", "()[I");
+    gNativeHandleFields.getIntsID = GetMethodIDOrDie(env, clazz, "getInts", "()[I");
+
+    return 0;
+}
+
+}
diff --git a/core/jni/android_os_NativeHandle.h b/core/jni/android_os_NativeHandle.h
new file mode 100644
index 0000000..bbe3ebc
--- /dev/null
+++ b/core/jni/android_os_NativeHandle.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_NATIVE_HANDLE_H
+#define ANDROID_OS_NATIVE_HANDLE_H
+
+#include "hwbinder/EphemeralStorage.h"
+
+#include <cutils/native_handle.h>
+#include <jni.h>
+
+namespace android {
+
+struct JNativeHandle {
+
+    /**
+     * Returns a Java NativeHandle object representing the parameterized
+     * native_handle_t instance.
+     */
+    static jobject MakeJavaNativeHandleObj(JNIEnv *env, const native_handle_t *handle);
+
+    /**
+     * Returns a heap-allocated native_handle_t instance representing the
+     * parameterized Java object. Note that if no valid EphemeralStorage*
+     * parameter is supplied (storage is nullptr), the return value must
+     * be explicitly deallocated (using native_handle_delete).
+     */
+    static native_handle_t* MakeCppNativeHandle(JNIEnv *env, jobject jHandle,
+            EphemeralStorage *storage);
+
+    /**
+     * Returns an (uninitialized) array of Java NativeHandle objects.
+     */
+    static jobjectArray AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length);
+};
+
+}
+
+#endif  // ANDROID_OS_NATIVE_HANDLE_H
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index bed239f..7ef06dc 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -336,8 +336,13 @@
                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
                 if (a2) {
                     const void* data = parcel->readInplace(len);
-                    memcpy(a2, data, len);
+                    if (data) {
+                        memcpy(a2, data, len);
+                    }
                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
+                    if (!data) {
+                        ret = NULL;
+                    }
                 }
             }
         }
@@ -360,9 +365,14 @@
         jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
         if (ar) {
             const void* data = parcel->readInplace(len);
-            memcpy(ar, data, len);
+            if (data) {
+                memcpy(ar, data, len);
+                ret = JNI_TRUE;
+            } else {
+                ret = JNI_FALSE;
+            }
+
             env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
-            ret = JNI_TRUE;
         }
     }
     return ret;
diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp
index 2dfbe3e..b68f9ec 100644
--- a/core/jni/android_util_MemoryIntArray.cpp
+++ b/core/jni/android_util_MemoryIntArray.cpp
@@ -142,8 +142,6 @@
         jniThrowException(env, "java/io/IOException", "ashmem unpinning failed");
         return;
     }
-
-    close(fd);
 }
 
 static jint android_util_MemoryIntArray_get(JNIEnv* env, jobject clazz,
diff --git a/core/jni/hwbinder/EphemeralStorage.cpp b/core/jni/hwbinder/EphemeralStorage.cpp
index 3b18f2b..95bb42e 100644
--- a/core/jni/hwbinder/EphemeralStorage.cpp
+++ b/core/jni/hwbinder/EphemeralStorage.cpp
@@ -71,6 +71,17 @@
     return s;
 }
 
+native_handle_t *EphemeralStorage::allocTemporaryNativeHandle(
+        int numFds, int numInts) {
+    Item item;
+    item.mType = TYPE_NATIVE_HANDLE;
+    item.mObj = nullptr;
+    item.mPtr = native_handle_create(numFds, numInts);
+    mItems.push_back(item);
+
+    return static_cast<native_handle_t*>(item.mPtr);
+}
+
 #define DEFINE_ALLOC_VECTOR_METHODS(Suffix,Type,NewType)                       \
 const hidl_vec<Type> *EphemeralStorage::allocTemporary ## Suffix ## Vector(    \
         JNIEnv *env, Type ## Array arrayObj) {                                 \
@@ -145,6 +156,13 @@
             DEFINE_RELEASE_ARRAY_CASE(Float,jfloat,Float)
             DEFINE_RELEASE_ARRAY_CASE(Double,jdouble,Double)
 
+            case TYPE_NATIVE_HANDLE:
+            {
+                int err = native_handle_delete(static_cast<native_handle_t *>(item.mPtr));
+                CHECK(err == 0);
+                break;
+            }
+
             default:
                 CHECK(!"Should not be here");
         }
diff --git a/core/jni/hwbinder/EphemeralStorage.h b/core/jni/hwbinder/EphemeralStorage.h
index f07c782..55ef741 100644
--- a/core/jni/hwbinder/EphemeralStorage.h
+++ b/core/jni/hwbinder/EphemeralStorage.h
@@ -43,6 +43,8 @@
     const ::android::hardware::hidl_string *allocTemporaryString(
             JNIEnv *env, jstring stringObj);
 
+    native_handle_t *allocTemporaryNativeHandle(int numFds, int numInts);
+
     DECLARE_ALLOC_METHODS(Int8,jbyte)
     DECLARE_ALLOC_METHODS(Int16,jshort)
     DECLARE_ALLOC_METHODS(Int32,jint)
@@ -61,6 +63,7 @@
         TYPE_Int64_ARRAY,
         TYPE_Float_ARRAY,
         TYPE_Double_ARRAY,
+        TYPE_NATIVE_HANDLE,
     };
 
     struct Item {
diff --git a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
index 57ee2d5..4b14284 100644
--- a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
+++ b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
@@ -21,36 +21,6 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 
-jint android_util_MemoryIntArrayTest_createAshmem(__attribute__((unused)) JNIEnv* env,
-        __attribute__((unused)) jobject clazz,
-        jstring name, jint size)
-{
-
-    if (name == NULL) {
-        return -1;
-    }
-
-    if (size < 0) {
-        return -1;
-    }
-
-    const char* nameStr = env->GetStringUTFChars(name, NULL);
-    const int ashmemSize = sizeof(std::atomic_int) * size;
-    int fd = ashmem_create_region(nameStr, ashmemSize);
-    env->ReleaseStringUTFChars(name, nameStr);
-
-    if (fd < 0) {
-        return -1;
-    }
-
-    int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
-    if (setProtResult < 0) {
-        return -1;
-    }
-
-    return fd;
-}
-
 void android_util_MemoryIntArrayTest_setAshmemSize(__attribute__((unused)) JNIEnv* env,
         __attribute__((unused)) jobject clazz, jint fd, jint size)
 {
diff --git a/core/tests/utiltests/jni/registration.cpp b/core/tests/utiltests/jni/registration.cpp
index 0c84d98..d4fc2fb 100644
--- a/core/tests/utiltests/jni/registration.cpp
+++ b/core/tests/utiltests/jni/registration.cpp
@@ -16,25 +16,14 @@
 
 #include <jni.h>
 
-extern jint android_util_MemoryIntArrayTest_createAshmem(JNIEnv* env,
-        jobject clazz, jstring name, jint size);
 extern void android_util_MemoryIntArrayTest_setAshmemSize(JNIEnv* env,
        jobject clazz, jint fd, jint size);
 
 extern "C" {
-    JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
-            JNIEnv * env, jobject obj, jstring name, jint size);
     JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
             JNIEnv * env, jobject obj, jint fd, jint size);
 };
 
-JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
-        __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
-        jstring name, jint size)
-{
-    return android_util_MemoryIntArrayTest_createAshmem(env, obj, name, size);
-}
-
 JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
         __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
         jint fd, jint size)
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
index 85817bb..24b33ef 100644
--- a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.support.test.runner.AndroidJUnit4;
 import libcore.io.IoUtils;
 import org.junit.Test;
@@ -251,13 +252,11 @@
                 // Create a MemoryIntArray to muck with
                 MemoryIntArray array = new MemoryIntArray(1);
 
-                // Create the fd to stuff in the MemoryIntArray
-                final int fd = nativeCreateAshmem("foo", 1);
-
-                // Replace the fd with our ahsmem region
-                Field fdFiled = MemoryIntArray.class.getDeclaredField("mFd");
-                fdFiled.setAccessible(true);
-                fdFiled.set(array, fd);
+                // Grab the internal ashmem fd.
+                Field fdField = MemoryIntArray.class.getDeclaredField("mFd");
+                fdField.setAccessible(true);
+                int fd = ((ParcelFileDescriptor)fdField.get(array)).getFd();
+                assertTrue("fd must be valid", fd != -1);
 
                 CountDownLatch countDownLatch = new CountDownLatch(2);
 
@@ -292,10 +291,9 @@
         }
 
         if (!success) {
-            fail("MemoryIntArray should catch ahshmem size changing under it");
+            fail("MemoryIntArray should catch ashmem size changing under it");
         }
     }
 
-    private native int nativeCreateAshmem(String name, int size);
     private native void nativeSetAshmemSize(int fd, int size);
 }
diff --git a/media/java/android/media/MediaHTTPService.java b/media/java/android/media/MediaHTTPService.java
index 3a0e58a..98517d1 100644
--- a/media/java/android/media/MediaHTTPService.java
+++ b/media/java/android/media/MediaHTTPService.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.Nullable;
 import android.os.IBinder;
 import android.util.Log;
 
@@ -28,10 +29,10 @@
 /** @hide */
 public class MediaHTTPService extends IMediaHTTPService.Stub {
     private static final String TAG = "MediaHTTPService";
-    private List<HttpCookie> mCookies;
+    @Nullable private List<HttpCookie> mCookies;
     private Boolean mCookieStoreInitialized = new Boolean(false);
 
-    public MediaHTTPService(List<HttpCookie> cookies) {
+    public MediaHTTPService(@Nullable List<HttpCookie> cookies) {
         mCookies = cookies;
         Log.v(TAG, "MediaHTTPService(" + this + "): Cookies: " + cookies);
     }
diff --git a/media/java/android/mtp/MtpPropertyList.java b/media/java/android/mtp/MtpPropertyList.java
index ede90da..557f099 100644
--- a/media/java/android/mtp/MtpPropertyList.java
+++ b/media/java/android/mtp/MtpPropertyList.java
@@ -16,6 +16,7 @@
 
 package android.mtp;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -49,6 +50,7 @@
         mStringValues = new ArrayList<>();
     }
 
+    @UnsupportedAppUsage
     public void append(int handle, int property, int type, long value) {
         mObjectHandles.add(handle);
         mPropertyCodes.add(property);
@@ -57,6 +59,7 @@
         mStringValues.add(null);
     }
 
+    @UnsupportedAppUsage
     public void append(int handle, int property, String value) {
         mObjectHandles.add(handle);
         mPropertyCodes.add(property);
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 2625e0c..c714b3c 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -16,6 +16,7 @@
 
 package android.mtp;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.storage.StorageVolume;
 
 /**
@@ -46,6 +47,7 @@
      *
      * @return the storage ID
      */
+    @UnsupportedAppUsage
     public final int getStorageId() {
         return mStorageId;
     }
@@ -55,6 +57,7 @@
      *
      * @return the storage file path
      */
+    @UnsupportedAppUsage
     public final String getPath() {
         return mPath;
     }
diff --git a/media/lib/remotedisplay/Android.bp b/media/lib/remotedisplay/Android.bp
new file mode 100644
index 0000000..1e9320d
--- /dev/null
+++ b/media/lib/remotedisplay/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+droiddoc {
+    name: "com.android.media.remotedisplay.stubs-gen-docs",
+    srcs: [
+        "java/**/*.java",
+    ],
+    args: " -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
+          " -stubpackages com.android.media.remotedisplay " +
+          " -nodocs ",
+    custom_template: "droiddoc-templates-sdk",
+    installable: false,
+}
+
+java_library_static {
+    name: "com.android.media.remotedisplay.stubs",
+    srcs: [
+        ":com.android.media.remotedisplay.stubs-gen-docs",
+    ],
+    sdk_version: "current",
+}
diff --git a/media/lib/remotedisplay/Android.mk b/media/lib/remotedisplay/Android.mk
index 63f9f91..e88c0f1 100644
--- a/media/lib/remotedisplay/Android.mk
+++ b/media/lib/remotedisplay/Android.mk
@@ -42,24 +42,3 @@
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 
 include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.media.remotedisplay.stubs-gen
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_SRC_FILES := $(call all-java-files-under,java)
-LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/com.android.media.remotedisplay.stubs_intermediates/src
-LOCAL_DROIDDOC_OPTIONS:= \
-    -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 \
-    -stubpackages com.android.media.remotedisplay \
-    -nodocs
-LOCAL_UNINSTALLABLE_MODULE := true
-include $(BUILD_DROIDDOC)
-com_android_media_remotedisplay_gen_stamp := $(full_target)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.media.remotedisplay.stubs
-LOCAL_SDK_VERSION := current
-LOCAL_SOURCE_FILES_ALL_GENERATED := true
-LOCAL_ADDITIONAL_DEPENDENCIES := $(com_android_media_remotedisplay_gen_stamp)
-com_android_media_remotedisplay_gen_stamp :=
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index f729120..c984579 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -976,7 +976,7 @@
 
     private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
         SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
-                null, null, null, "");
+                null, null, null, "", false, null, null);
         MobileSignalController controller = new MobileSignalController(mContext,
                 mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
                 mSubDefaults, mReceiverHandler.getLooper());
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6b3f8f8..ba5f323 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2194,8 +2194,7 @@
                     break;
                 }
                 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
-                    Integer score = (Integer) msg.obj;
-                    if (score != null) updateNetworkScore(nai, score.intValue());
+                    updateNetworkScore(nai, msg.arg1);
                     break;
                 }
                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
@@ -2203,7 +2202,7 @@
                         loge("ERROR: already-connected network explicitly selected.");
                     }
                     nai.networkMisc.explicitlySelected = true;
-                    nai.networkMisc.acceptUnvalidated = (boolean) msg.obj;
+                    nai.networkMisc.acceptUnvalidated = msg.arg1 == 1;
                     break;
                 }
                 case NetworkAgent.EVENT_PACKET_KEEPALIVE: {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 3791402..0d60d1d 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -641,12 +641,7 @@
 
             SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
 
-            try {
-                mConnector.execute("strict", "enable");
-                mStrictEnabled = true;
-            } catch (NativeDaemonConnectorException e) {
-                Log.wtf(TAG, "Failed strict enable", e);
-            }
+            mStrictEnabled = true;
 
             setDataSaverModeEnabled(mDataSaverMode);
 
@@ -1804,26 +1799,26 @@
     }
 
     private void applyUidCleartextNetworkPolicy(int uid, int policy) {
-        final String policyString;
+        final int policyValue;
         switch (policy) {
             case StrictMode.NETWORK_POLICY_ACCEPT:
-                policyString = "accept";
+                policyValue = INetd.PENALTY_POLICY_ACCEPT;
                 break;
             case StrictMode.NETWORK_POLICY_LOG:
-                policyString = "log";
+                policyValue = INetd.PENALTY_POLICY_LOG;
                 break;
             case StrictMode.NETWORK_POLICY_REJECT:
-                policyString = "reject";
+                policyValue = INetd.PENALTY_POLICY_REJECT;
                 break;
             default:
                 throw new IllegalArgumentException("Unknown policy " + policy);
         }
 
         try {
-            mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
+            mNetdService.strictUidCleartextPenalty(uid, policyValue);
             mUidCleartextPolicy.put(uid, policy);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1841,6 +1836,7 @@
                 return;
             }
 
+            // TODO: remove this code after removing prepareNativeDaemon()
             if (!mStrictEnabled) {
                 // Module isn't enabled yet; stash the requested policy away to
                 // apply later once the daemon is connected.
@@ -2307,9 +2303,9 @@
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
         try {
-            mConnector.execute("clatd", "start", interfaceName);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.clatdStart(interfaceName);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -2318,28 +2314,13 @@
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
         try {
-            mConnector.execute("clatd", "stop", interfaceName);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.clatdStop(interfaceName);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
     @Override
-    public boolean isClatdStarted(String interfaceName) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        final NativeDaemonEvent event;
-        try {
-            event = mConnector.execute("clatd", "status", interfaceName);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-
-        event.checkCode(ClatdStatusResult);
-        return event.getMessage().endsWith("started");
-    }
-
-    @Override
     public void registerNetworkActivityListener(INetworkActivityListener listener) {
         mNetworkActivityListeners.register(listener);
     }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index b0be4a9..cf49d2a 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -409,7 +409,7 @@
                 // TODO(calin): maybe add a separate call.
                 mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0,
                         /*oatDir*/ null, dexoptFlags,
-                        compilerFilter, info.volumeUuid, classLoaderContext, info.seInfoUser,
+                        compilerFilter, info.volumeUuid, classLoaderContext, info.seInfo,
                         options.isDowngrade(), info.targetSdkVersion, /*profileName*/ null,
                         /*dexMetadataPath*/ null, getReasonName(reason));
             }
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 2a41829..c240dbb 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -17,14 +17,11 @@
 package android.telephony;
 
 import android.annotation.CallSuper;
-import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
@@ -32,44 +29,6 @@
  * CellIdentityXxx which represents cell identity for specific network access technology.
  */
 public abstract class CellIdentity implements Parcelable {
-    /**
-     * Cell identity type
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
-    public @interface Type {}
-
-    /**
-     * Unknown cell identity type
-     * @hide
-     */
-    public static final int TYPE_UNKNOWN        = 0;
-    /**
-     * GSM cell identity type
-     * @hide
-     */
-    public static final int TYPE_GSM            = 1;
-    /**
-     * CDMA cell identity type
-     * @hide
-     */
-    public static final int TYPE_CDMA           = 2;
-    /**
-     * LTE cell identity type
-     * @hide
-     */
-    public static final int TYPE_LTE            = 3;
-    /**
-     * WCDMA cell identity type
-     * @hide
-     */
-    public static final int TYPE_WCDMA          = 4;
-    /**
-     * TDS-CDMA cell identity type
-     * @hide
-     */
-    public static final int TYPE_TDSCDMA        = 5;
 
     /** @hide */
     public static final int INVALID_CHANNEL_NUMBER = -1;
@@ -138,7 +97,9 @@
      * @hide
      * @return The type of the cell identity
      */
-    public @Type int getType() { return mType; }
+    public @CellInfo.Type int getType() {
+        return mType;
+    }
 
     /**
      * Returns the channel number of the cell identity.
@@ -217,11 +178,12 @@
                 public CellIdentity createFromParcel(Parcel in) {
                     int type = in.readInt();
                     switch (type) {
-                        case TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
-                        case TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
-                        case TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
-                        case TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
-                        case TYPE_TDSCDMA: return CellIdentityTdscdma.createFromParcelBody(in);
+                        case CellInfo.TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
+                        case CellInfo.TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
+                        case CellInfo.TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
+                        case CellInfo.TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
+                        case CellInfo.TYPE_TDSCDMA:
+                            return CellIdentityTdscdma.createFromParcelBody(in);
                         default: throw new IllegalArgumentException("Bad Cell identity Parcel");
                     }
                 }
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 58a2c45..2809066 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -54,7 +54,7 @@
      * @hide
      */
     public CellIdentityCdma() {
-        super(TAG, TYPE_CDMA, null, null, null, null);
+        super(TAG, CellInfo.TYPE_CDMA, null, null, null, null);
         mNetworkId = Integer.MAX_VALUE;
         mSystemId = Integer.MAX_VALUE;
         mBasestationId = Integer.MAX_VALUE;
@@ -94,7 +94,7 @@
      */
     public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat, String alphal,
                              String alphas) {
-        super(TAG, TYPE_CDMA, null, null, alphal, alphas);
+        super(TAG, CellInfo.TYPE_CDMA, null, null, alphal, alphas);
         mNetworkId = nid;
         mSystemId = sid;
         mBasestationId = bid;
@@ -213,7 +213,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_CDMA);
+        super.writeToParcel(dest, CellInfo.TYPE_CDMA);
         dest.writeInt(mNetworkId);
         dest.writeInt(mSystemId);
         dest.writeInt(mBasestationId);
@@ -223,7 +223,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityCdma(Parcel in) {
-        super(TAG, TYPE_CDMA, in);
+        super(TAG, CellInfo.TYPE_CDMA, in);
         mNetworkId = in.readInt();
         mSystemId = in.readInt();
         mBasestationId = in.readInt();
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index c697880..4031254 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -42,7 +42,7 @@
      * @hide
      */
     public CellIdentityGsm() {
-        super(TAG, TYPE_GSM, null, null, null, null);
+        super(TAG, CellInfo.TYPE_GSM, null, null, null, null);
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
         mArfcn = Integer.MAX_VALUE;
@@ -92,7 +92,7 @@
      */
     public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, String mccStr,
                             String mncStr, String alphal, String alphas) {
-        super(TAG, TYPE_GSM, mccStr, mncStr, alphal, alphas);
+        super(TAG, CellInfo.TYPE_GSM, mccStr, mncStr, alphal, alphas);
         mLac = lac;
         mCid = cid;
         mArfcn = arfcn;
@@ -237,7 +237,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_GSM);
+        super.writeToParcel(dest, CellInfo.TYPE_GSM);
         dest.writeInt(mLac);
         dest.writeInt(mCid);
         dest.writeInt(mArfcn);
@@ -246,7 +246,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityGsm(Parcel in) {
-        super(TAG, TYPE_GSM, in);
+        super(TAG, CellInfo.TYPE_GSM, in);
         mLac = in.readInt();
         mCid = in.readInt();
         mArfcn = in.readInt();
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 177fced..5257372 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -44,7 +44,7 @@
      * @hide
      */
     public CellIdentityLte() {
-        super(TAG, TYPE_LTE, null, null, null, null);
+        super(TAG, CellInfo.TYPE_LTE, null, null, null, null);
         mCi = Integer.MAX_VALUE;
         mPci = Integer.MAX_VALUE;
         mTac = Integer.MAX_VALUE;
@@ -99,7 +99,7 @@
      */
     public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, String mccStr,
             String mncStr, String alphal, String alphas) {
-        super(TAG, TYPE_LTE, mccStr, mncStr, alphal, alphas);
+        super(TAG, CellInfo.TYPE_LTE, mccStr, mncStr, alphal, alphas);
         mCi = ci;
         mPci = pci;
         mTac = tac;
@@ -241,7 +241,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_LTE);
+        super.writeToParcel(dest, CellInfo.TYPE_LTE);
         dest.writeInt(mCi);
         dest.writeInt(mPci);
         dest.writeInt(mTac);
@@ -251,7 +251,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityLte(Parcel in) {
-        super(TAG, TYPE_LTE, in);
+        super(TAG, CellInfo.TYPE_LTE, in);
         mCi = in.readInt();
         mPci = in.readInt();
         mTac = in.readInt();
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index b99fe46..21b9601 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -40,7 +40,7 @@
      * @hide
      */
     public CellIdentityTdscdma() {
-        super(TAG, TYPE_TDSCDMA, null, null, null, null);
+        super(TAG, CellInfo.TYPE_TDSCDMA, null, null, null, null);
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
         mCpid = Integer.MAX_VALUE;
@@ -75,7 +75,7 @@
      */
     public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid, int uarfcn,
             String alphal, String alphas) {
-        super(TAG, TYPE_TDSCDMA, mcc, mnc, alphal, alphas);
+        super(TAG, CellInfo.TYPE_TDSCDMA, mcc, mnc, alphal, alphas);
         mLac = lac;
         mCid = cid;
         mCpid = cpid;
@@ -175,7 +175,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_TDSCDMA);
+        super.writeToParcel(dest, CellInfo.TYPE_TDSCDMA);
         dest.writeInt(mLac);
         dest.writeInt(mCid);
         dest.writeInt(mCpid);
@@ -184,7 +184,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityTdscdma(Parcel in) {
-        super(TAG, TYPE_TDSCDMA, in);
+        super(TAG, CellInfo.TYPE_TDSCDMA, in);
         mLac = in.readInt();
         mCid = in.readInt();
         mCpid = in.readInt();
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 43f9406..a4ac8e3 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -42,7 +42,7 @@
      * @hide
      */
     public CellIdentityWcdma() {
-        super(TAG, TYPE_TDSCDMA, null, null, null, null);
+        super(TAG, CellInfo.TYPE_WCDMA, null, null, null, null);
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
         mPsc = Integer.MAX_VALUE;
@@ -93,7 +93,7 @@
      */
     public CellIdentityWcdma (int lac, int cid, int psc, int uarfcn,
                               String mccStr, String mncStr, String alphal, String alphas) {
-        super(TAG, TYPE_WCDMA, mccStr, mncStr, alphal, alphas);
+        super(TAG, CellInfo.TYPE_WCDMA, mccStr, mncStr, alphal, alphas);
         mLac = lac;
         mCid = cid;
         mPsc = psc;
@@ -227,7 +227,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_WCDMA);
+        super.writeToParcel(dest, CellInfo.TYPE_WCDMA);
         dest.writeInt(mLac);
         dest.writeInt(mCid);
         dest.writeInt(mPsc);
@@ -236,7 +236,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityWcdma(Parcel in) {
-        super(TAG, TYPE_WCDMA, in);
+        super(TAG, CellInfo.TYPE_WCDMA, in);
         mLac = in.readInt();
         mCid = in.readInt();
         mPsc = in.readInt();
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index bffeb17..6b320f4 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -29,17 +29,43 @@
  */
 public abstract class CellInfo implements Parcelable {
 
-    // Type fields for parceling
-    /** @hide */
-    protected static final int TYPE_GSM = 1;
-    /** @hide */
-    protected static final int TYPE_CDMA = 2;
-    /** @hide */
-    protected static final int TYPE_LTE = 3;
-    /** @hide */
-    protected static final int TYPE_WCDMA = 4;
-    /** @hide */
-    protected static final int TYPE_TDCDMA = 5;
+    /**
+     * Cell identity type
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
+    public @interface Type {}
+    /**
+     * Unknown cell identity type
+     * @hide
+     */
+    public static final int TYPE_UNKNOWN        = 0;
+    /**
+     * GSM cell identity type
+     * @hide
+     */
+    public static final int TYPE_GSM            = 1;
+    /**
+     * CDMA cell identity type
+     * @hide
+     */
+    public static final int TYPE_CDMA           = 2;
+    /**
+     * LTE cell identity type
+     * @hide
+     */
+    public static final int TYPE_LTE            = 3;
+    /**
+     * WCDMA cell identity type
+     * @hide
+     */
+    public static final int TYPE_WCDMA          = 4;
+    /**
+     * TD-SCDMA cell identity type
+     * @hide
+     */
+    public static final int TYPE_TDSCDMA        = 5;
 
     // Type to distinguish where time stamp gets recorded.
 
@@ -161,6 +187,7 @@
     public int getTimeStampType() {
         return mTimeStampType;
     }
+
     /** @hide */
     public void setTimeStampType(int timeStampType) {
         if (timeStampType < TIMESTAMP_TYPE_UNKNOWN || timeStampType > TIMESTAMP_TYPE_JAVA_RIL) {
@@ -272,7 +299,7 @@
                     case TYPE_CDMA: return CellInfoCdma.createFromParcelBody(in);
                     case TYPE_LTE: return CellInfoLte.createFromParcelBody(in);
                     case TYPE_WCDMA: return CellInfoWcdma.createFromParcelBody(in);
-                    case TYPE_TDCDMA: return CellInfoTdscdma.createFromParcelBody(in);
+                    case TYPE_TDSCDMA: return CellInfoTdscdma.createFromParcelBody(in);
                     default: throw new RuntimeException("Bad CellInfo Parcel");
                 }
         }
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index 4fb1bce..40cadde 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -110,7 +110,7 @@
     /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags, TYPE_TDCDMA);
+        super.writeToParcel(dest, flags, TYPE_TDSCDMA);
         mCellIdentityTdscdma.writeToParcel(dest, flags);
         mCellSignalStrengthTdscdma.writeToParcel(dest, flags);
     }
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index d76e39b..667ad91 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -139,28 +139,6 @@
      */
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
-            Bitmap icon, String mcc, String mnc, String countryIso) {
-        this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
-                roaming, icon, mcc, mnc, countryIso, false /* isEmbedded */,
-                null /* accessRules */, null /* accessRules */);
-    }
-
-    /**
-     * @hide
-     */
-    public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
-            CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
-            Bitmap icon, String mcc, String mnc, String countryIso,  boolean isEmbedded,
-            @Nullable UiccAccessRule[] accessRules) {
-        this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
-                roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, null /* cardId */);
-    }
-
-    /**
-     * @hide
-     */
-    public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
-            CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
             Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
             @Nullable UiccAccessRule[] accessRules, String cardId) {
         this.mId = id;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 63b3b81..eda6192 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6680,14 +6680,12 @@
     @Deprecated
     public boolean isTtyModeSupported() {
         try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                return telephony.isTtyModeSupported();
+            TelecomManager telecomManager = TelecomManager.from(mContext);
+            if (telecomManager != null) {
+                return telecomManager.isTtySupported();
             }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#isTtyModeSupported", e);
         } catch (SecurityException e) {
-            Log.e(TAG, "Permission error calling ITelephony#isTtyModeSupported", e);
+            Log.e(TAG, "Permission error calling TelecomManager#isTtySupported", e);
         }
         return false;
     }