Merge "Implement broker pattern for imms (1/3)" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 046056a..6463adb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12706,7 +12706,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_PHYSICAL_SIZE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_PIXEL_ARRAY_SIZE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_SENSITIVITY_RANGE;
-    field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_TIMESTAMP_CALIBRATION;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_TIMESTAMP_SOURCE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_WHITE_LEVEL;
     field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_MAX_ANALOG_SENSITIVITY;
     field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_ORIENTATION;
@@ -12900,8 +12900,8 @@
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4; // 0x4
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0; // 0x0
-    field public static final int SENSOR_INFO_TIMESTAMP_CALIBRATION_CALIBRATED = 1; // 0x1
-    field public static final int SENSOR_INFO_TIMESTAMP_CALIBRATION_UNCALIBRATED = 0; // 0x0
+    field public static final int SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME = 1; // 0x1
+    field public static final int SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN = 0; // 0x0
     field public static final int SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER = 10; // 0xa
     field public static final int SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT = 14; // 0xe
     field public static final int SENSOR_REFERENCE_ILLUMINANT1_D50 = 23; // 0x17
@@ -13211,7 +13211,6 @@
     method public boolean isOutputSupportedFor(int);
     method public static boolean isOutputSupportedFor(java.lang.Class<T>);
     method public boolean isOutputSupportedFor(android.view.Surface);
-    field public static final long NO_MIN_FRAME_DURATION = 0L; // 0x0L
   }
 
   public final class TonemapCurve {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0e6f86e..9310bf8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -361,6 +361,40 @@
             = "android.app.action.ADD_DEVICE_ADMIN";
 
     /**
+     * @hide
+     * Activity action: ask the user to add a new device administrator as the profile owner
+     * for this user. Only system privileged apps that have MANAGE_USERS and MANAGE_DEVICE_ADMINS
+     * permission can call this API.
+     *
+     * <p>The ComponentName of the profile owner admin is pass in {@link #EXTRA_DEVICE_ADMIN} extra
+     * field. This will invoke a UI to bring the user through adding the profile owner admin
+     * to remotely control restrictions on the user.
+     *
+     * <p>The intent must be invoked via {@link Activity#startActivityForResult()} to receive the
+     * result of whether or not the user approved the action. If approved, the result will
+     * be {@link Activity#RESULT_OK} and the component will be set as an active admin as well
+     * as a profile owner.
+     *
+     * <p>You can optionally include the {@link #EXTRA_ADD_EXPLANATION}
+     * field to provide the user with additional explanation (in addition
+     * to your component's description) about what is being added.
+     *
+     * <p>If there is already a profile owner active or the caller doesn't have the required
+     * permissions, the operation will return a failure result.
+     */
+    @SystemApi
+    public static final String ACTION_SET_PROFILE_OWNER
+            = "android.app.action.SET_PROFILE_OWNER";
+
+    /**
+     * @hide
+     * Name of the profile owner admin that controls the user.
+     */
+    @SystemApi
+    public static final String EXTRA_PROFILE_OWNER_NAME
+            = "android.app.extra.PROFILE_OWNER_NAME";
+
+    /**
      * Activity action: send when any policy admin changes a policy.
      * This is generally used to find out when a new policy is in effect.
      *
@@ -397,6 +431,7 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SET_NEW_PASSWORD
             = "android.app.action.SET_NEW_PASSWORD";
+
     /**
      * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a
      * managed profile to its parent.
@@ -2018,7 +2053,6 @@
         return false;
     }
 
-
     /**
      * Used to determine if a particular package has been registered as a Device Owner app.
      * A device owner app is a special device admin that cannot be deactivated by the user, once
@@ -2096,6 +2130,7 @@
 
     /**
      * @hide
+     * @deprecated Use #ACTION_SET_PROFILE_OWNER
      * Sets the given component as an active admin and registers the package as the profile
      * owner for this user. The package must already be installed and there shouldn't be
      * an existing profile owner registered for this user. Also, this method must be called
@@ -2116,7 +2151,7 @@
             try {
                 final int myUserId = UserHandle.myUserId();
                 mService.setActiveAdmin(admin, false, myUserId);
-                return mService.setProfileOwner(admin.getPackageName(), ownerName, myUserId);
+                return mService.setProfileOwner(admin, ownerName, myUserId);
             } catch (RemoteException re) {
                 Log.w(TAG, "Failed to set profile owner " + re);
                 throw new IllegalArgumentException("Couldn't set profile owner.", re);
@@ -2127,6 +2162,42 @@
 
     /**
      * @hide
+     * Clears the active profile owner and removes all user restrictions. The caller must
+     * be from the same package as the active profile owner for this user, otherwise a
+     * SecurityException will be thrown.
+     *
+     * @param admin The component to remove as the profile owner.
+     * @return
+     */
+    @SystemApi
+    public void clearProfileOwner(ComponentName admin) {
+        if (mService != null) {
+            try {
+                mService.clearProfileOwner(admin);
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed to clear profile owner " + admin + re);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     * Checks if the user was already setup.
+     */
+    public boolean hasUserSetupCompleted() {
+        if (mService != null) {
+            try {
+                return mService.hasUserSetupCompleted();
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed to check if user setup has completed");
+            }
+        }
+        return true;
+    }
+
+    /**
+     * @deprecated Use setProfileOwner(ComponentName ...)
+     * @hide
      * Sets the given package as the profile owner of the given user profile. The package must
      * already be installed and there shouldn't be an existing profile owner registered for this
      * user. Also, this method must be called before the user has been used for the first time.
@@ -2139,9 +2210,35 @@
      */
     public boolean setProfileOwner(String packageName, String ownerName, int userHandle)
             throws IllegalArgumentException {
+        if (packageName == null) {
+            throw new NullPointerException("packageName cannot be null");
+        }
+        return setProfileOwner(new ComponentName(packageName, ""), ownerName, userHandle);
+    }
+
+    /**
+     * @hide
+     * Sets the given component as the profile owner of the given user profile. The package must
+     * already be installed and there shouldn't be an existing profile owner registered for this
+     * user. Only the system can call this API if the user has already completed setup.
+     * @param admin the component name to be registered as profile owner.
+     * @param ownerName the human readable name of the organisation associated with this DPM.
+     * @param userHandle the userId to set the profile owner for.
+     * @return whether the component was successfully registered as the profile owner.
+     * @throws IllegalArgumentException if admin is null, the package isn't installed, or
+     *         the user has already been set up.
+     */
+    public boolean setProfileOwner(ComponentName admin, String ownerName, int userHandle)
+            throws IllegalArgumentException {
+        if (admin == null) {
+            throw new NullPointerException("admin cannot be null");
+        }
         if (mService != null) {
             try {
-                return mService.setProfileOwner(packageName, ownerName, userHandle);
+                if (ownerName == null) {
+                    ownerName = "";
+                }
+                return mService.setProfileOwner(admin, ownerName, userHandle);
             } catch (RemoteException re) {
                 Log.w(TAG, "Failed to set profile owner", re);
                 throw new IllegalArgumentException("Couldn't set profile owner.", re);
@@ -2200,7 +2297,7 @@
         if (mService != null) {
             try {
                 String profileOwnerPackage = mService.getProfileOwner(
-                        Process.myUserHandle().getIdentifier());
+                        Process.myUserHandle().getIdentifier()).getPackageName();
                 return profileOwnerPackage != null && profileOwnerPackage.equals(packageName);
             } catch (RemoteException re) {
                 Log.w(TAG, "Failed to check profile owner");
@@ -2215,7 +2312,7 @@
      * owner has been set for that user.
      * @throws IllegalArgumentException if the userId is invalid.
      */
-    public String getProfileOwner() throws IllegalArgumentException {
+    public ComponentName getProfileOwner() throws IllegalArgumentException {
         if (mService != null) {
             try {
                 return mService.getProfileOwner(Process.myUserHandle().getIdentifier());
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a6544e6..6ce737a 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -113,11 +113,13 @@
     String getDeviceOwnerName();
     void clearDeviceOwner(String packageName);
 
-    boolean setProfileOwner(String packageName, String ownerName, int userHandle);
-    String getProfileOwner(int userHandle);
+    boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle);
+    ComponentName getProfileOwner(int userHandle);
     String getProfileOwnerName(int userHandle);
     void setProfileEnabled(in ComponentName who);
     void setProfileName(in ComponentName who, String profileName);
+    void clearProfileOwner(in ComponentName who);
+    boolean hasUserSetupCompleted();
 
     boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
     void uninstallCaCert(in ComponentName admin, in String alias);
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 2ce18b0..30aaf2e 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -110,21 +110,27 @@
         dest.writeInt(mServiceDataUuid == null ? 0 : 1);
         if (mServiceDataUuid != null) {
             dest.writeParcelable(mServiceDataUuid, flags);
-            dest.writeInt(mServiceData == null ? 0 : mServiceData.length);
+            dest.writeInt(mServiceData == null ? 0 : 1);
             if (mServiceData != null) {
+                dest.writeInt(mServiceData.length);
                 dest.writeByteArray(mServiceData);
-                dest.writeInt(mServiceDataMask == null ? 0 : mServiceDataMask.length);
+
+                dest.writeInt(mServiceDataMask == null ? 0 : 1);
                 if (mServiceDataMask != null) {
+                    dest.writeInt(mServiceDataMask.length);
                     dest.writeByteArray(mServiceDataMask);
                 }
             }
         }
         dest.writeInt(mManufacturerId);
-        dest.writeInt(mManufacturerData == null ? 0 : mManufacturerData.length);
+        dest.writeInt(mManufacturerData == null ? 0 : 1);
         if (mManufacturerData != null) {
+            dest.writeInt(mManufacturerData.length);
             dest.writeByteArray(mManufacturerData);
-            dest.writeInt(mManufacturerDataMask == null ? 0 : mManufacturerDataMask.length);
+
+            dest.writeInt(mManufacturerDataMask == null ? 0 : 1);
             if (mManufacturerDataMask != null) {
+                dest.writeInt(mManufacturerDataMask.length);
                 dest.writeByteArray(mManufacturerDataMask);
             }
         }
@@ -164,29 +170,31 @@
                     if (in.readInt() == 1) {
                         ParcelUuid servcieDataUuid =
                                 in.readParcelable(ParcelUuid.class.getClassLoader());
-                        int serviceDataLength = in.readInt();
-                        if (serviceDataLength > 0) {
+                        if (in.readInt() == 1) {
+                            int serviceDataLength = in.readInt();
                             byte[] serviceData = new byte[serviceDataLength];
                             in.readByteArray(serviceData);
-                            builder.setServiceData(servcieDataUuid, serviceData);
-                            int serviceDataMaskLength = in.readInt();
-                            if (serviceDataMaskLength > 0) {
+                            if (in.readInt() == 0) {
+                                builder.setServiceData(servcieDataUuid, serviceData);
+                            } else {
+                                int serviceDataMaskLength = in.readInt();
                                 byte[] serviceDataMask = new byte[serviceDataMaskLength];
                                 in.readByteArray(serviceDataMask);
                                 builder.setServiceData(
-                                        servcieDataUuid, serviceData, serviceDataMask);
+                                            servcieDataUuid, serviceData, serviceDataMask);
                             }
                         }
                     }
 
                     int manufacturerId = in.readInt();
-                    int manufacturerDataLength = in.readInt();
-                    if (manufacturerDataLength > 0) {
+                    if (in.readInt() == 1) {
+                        int manufacturerDataLength = in.readInt();
                         byte[] manufacturerData = new byte[manufacturerDataLength];
                         in.readByteArray(manufacturerData);
-                        builder.setManufacturerData(manufacturerId, manufacturerData);
-                        int manufacturerDataMaskLength = in.readInt();
-                        if (manufacturerDataMaskLength > 0) {
+                        if (in.readInt() == 0) {
+                            builder.setManufacturerData(manufacturerId, manufacturerData);
+                        } else {
+                            int manufacturerDataMaskLength = in.readInt();
                             byte[] manufacturerDataMask = new byte[manufacturerDataMaskLength];
                             in.readByteArray(manufacturerDataMask);
                             builder.setManufacturerData(manufacturerId, manufacturerData,
@@ -349,12 +357,17 @@
 
     // Check whether the data pattern matches the parsed data.
     private boolean matchesPartialData(byte[] data, byte[] dataMask, byte[] parsedData) {
-        if (dataMask == null) {
-            return Arrays.equals(data, parsedData);
-        }
-        if (parsedData == null) {
+        if (parsedData == null || parsedData.length < data.length) {
             return false;
         }
+        if (dataMask == null) {
+            for (int i = 0; i < data.length; ++i) {
+                if (parsedData[i] != data[i]) {
+                    return false;
+                }
+            }
+            return true;
+        }
         for (int i = 0; i < data.length; ++i) {
             if ((dataMask[i] & parsedData[i]) != (dataMask[i] & data[i])) {
                 return false;
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 2d50b5a..c95a5bf 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -190,7 +190,7 @@
                 return info;
             }
         } catch (RemoteException re) {
-            return null;
+            throw new RuntimeException("Failed to call LauncherAppsService");
         }
         return null;
     }
@@ -259,7 +259,7 @@
         try {
             return mService.isPackageEnabled(packageName, user);
         } catch (RemoteException re) {
-            return false;
+            throw new RuntimeException("Failed to call LauncherAppsService");
         }
     }
 
@@ -275,7 +275,7 @@
         try {
             return mService.isActivityEnabled(component, user);
         } catch (RemoteException re) {
-            return false;
+            throw new RuntimeException("Failed to call LauncherAppsService");
         }
     }
 
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index dd16f6f..4e7f9dd 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1551,17 +1551,17 @@
             new Key<Integer>("android.sensor.info.whiteLevel", int.class);
 
     /**
-     * <p>The sensor timestamp calibration quality.</p>
-     * <p>The sensor timestamp calibration quality determines the reliability of
-     * {@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp} provided by the camera device.</p>
-     *
-     * @see CaptureResult#SENSOR_TIMESTAMP
-     * @see #SENSOR_INFO_TIMESTAMP_CALIBRATION_UNCALIBRATED
-     * @see #SENSOR_INFO_TIMESTAMP_CALIBRATION_CALIBRATED
+     * <p>The time base source for sensor capture start timestamps.</p>
+     * <p>The timestamps provided for captures are always in nanoseconds and monotonic, but
+     * may not based on a time source that can be compared to other system time sources.</p>
+     * <p>This characteristic defines the source for the timestamps, and therefore whether they
+     * can be compared against other system time sources/timestamps.</p>
+     * @see #SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN
+     * @see #SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME
      */
     @PublicKey
-    public static final Key<Integer> SENSOR_INFO_TIMESTAMP_CALIBRATION =
-            new Key<Integer>("android.sensor.info.timestampCalibration", int.class);
+    public static final Key<Integer> SENSOR_INFO_TIMESTAMP_SOURCE =
+            new Key<Integer>("android.sensor.info.timestampSource", int.class);
 
     /**
      * <p>The standard reference illuminant used as the scene light source when
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 9f7ae60..fbca395 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -494,7 +494,7 @@
     public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4;
 
     //
-    // Enumeration values for CameraCharacteristics#SENSOR_INFO_TIMESTAMP_CALIBRATION
+    // Enumeration values for CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
     //
 
     /**
@@ -506,9 +506,9 @@
      * and the result metadata generated by a single capture are identical.</p>
      *
      * @see CaptureResult#SENSOR_TIMESTAMP
-     * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_CALIBRATION
+     * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
      */
-    public static final int SENSOR_INFO_TIMESTAMP_CALIBRATION_UNCALIBRATED = 0;
+    public static final int SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN = 0;
 
     /**
      * <p>Timestamps from {@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp} are in the same timebase as
@@ -516,9 +516,9 @@
      * and they can be compared to other timestamps using that base.</p>
      *
      * @see CaptureResult#SENSOR_TIMESTAMP
-     * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_CALIBRATION
+     * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
      */
-    public static final int SENSOR_INFO_TIMESTAMP_CALIBRATION_CALIBRATED = 1;
+    public static final int SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME = 1;
 
     //
     // Enumeration values for CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
@@ -1208,8 +1208,7 @@
      * image while recording video) use case.</p>
      * <p>The camera device should take the highest-quality image
      * possible (given the other settings) without disrupting the
-     * frame rate of video recording.<br />
-     * </p>
+     * frame rate of video recording.  </p>
      * @see CaptureRequest#CONTROL_CAPTURE_INTENT
      */
     public static final int CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT = 4;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 4f80bc4..63dff55 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2221,18 +2221,18 @@
      * <p>The timestamps are also included in all image
      * buffers produced for the same capture, and will be identical
      * on all the outputs.</p>
-     * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_CALIBRATION android.sensor.info.timestampCalibration} <code>==</code> UNCALIBRATED,
+     * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} <code>==</code> UNKNOWN,
      * the timestamps measure time since an unspecified starting point,
      * and are monotonically increasing. They can be compared with the
      * timestamps for other captures from the same camera device, but are
      * not guaranteed to be comparable to any other time source.</p>
-     * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_CALIBRATION android.sensor.info.timestampCalibration} <code>==</code> CALIBRATED,
+     * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} <code>==</code> REALTIME,
      * the timestamps measure time in the same timebase as
      * android.os.SystemClock#elapsedRealtimeNanos(), and they can be
      * compared to other timestamps from other subsystems that are using
      * that base.</p>
      *
-     * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_CALIBRATION
+     * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
      */
     @PublicKey
     public static final Key<Long> SENSOR_TIMESTAMP =
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index c31f59e..1efabb1 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -67,11 +67,6 @@
     private static final String TAG = "StreamConfigurationMap";
 
     /**
-     * Indicates that a minimum frame duration is not available for a particular configuration.
-     */
-    public static final long NO_MIN_FRAME_DURATION = 0;
-
-    /**
      * Create a new {@link StreamConfigurationMap}.
      *
      * <p>The array parameters ownership is passed to this object after creation; do not
@@ -536,7 +531,7 @@
      *
      * <p>For devices that do not support manual sensor control
      * ({@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR}),
-     * this function may return {@link #NO_MIN_FRAME_DURATION}.</p>
+     * this function may return 0.</p>
      *
      * <!--
      * TODO: uncomment after adding input stream support
@@ -547,7 +542,7 @@
      * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
      * @param size an output-compatible size
      * @return a minimum frame duration {@code >} 0 in nanoseconds, or
-     *          {@link #NO_MIN_FRAME_DURATION} if the minimum frame duration is not available.
+     *          0 if the minimum frame duration is not available.
      *
      * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
      * @throws NullPointerException if {@code size} was {@code null}
@@ -586,7 +581,7 @@
      *
      * <p>For devices that do not support manual sensor control
      * ({@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR}),
-     * this function may return {@link #NO_MIN_FRAME_DURATION}.</p>
+     * this function may return 0.</p>
      *
      * <!--
      * TODO: uncomment after adding input stream support
@@ -599,7 +594,7 @@
      *          non-empty array returned by {@link #getOutputSizes(Class)}
      * @param size an output-compatible size
      * @return a minimum frame duration {@code >} 0 in nanoseconds, or
-     *          {@link #NO_MIN_FRAME_DURATION} if the minimum frame duration is not available.
+     *          0 if the minimum frame duration is not available.
      *
      * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
      * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
@@ -1065,8 +1060,8 @@
                 return configurationDuration.getDuration();
             }
         }
-
-        return getDurationDefault(duration);
+        // Default duration is '0' (unsupported/no extra stall)
+        return 0;
     }
 
     /**
@@ -1086,17 +1081,6 @@
         }
     }
 
-    private long getDurationDefault(int duration) {
-        switch (duration) {
-            case DURATION_MIN_FRAME:
-                return NO_MIN_FRAME_DURATION;
-            case DURATION_STALL:
-                return 0L; // OK. A lack of a stall duration implies a 0 stall duration
-            default:
-                throw new IllegalArgumentException("duration was invalid");
-        }
-    }
-
     /** Count the number of publicly-visible output formats */
     private int getPublicFormatCount(boolean output) {
         HashMap<Integer, Integer> formatsMap = getFormatsMap(output);
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 2fc3892..9215853 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -236,6 +236,7 @@
         }
         Intent intent = new Intent(ACTION_SCORE_NETWORKS);
         intent.setPackage(activeScorer);
+        intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(EXTRA_NETWORKS_TO_SCORE, networks);
         mContext.sendBroadcast(intent);
         return true;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a506c42..9935317 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -615,6 +615,12 @@
         if (guest != null) {
             Settings.Secure.putStringForUser(context.getContentResolver(),
                     Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
+            try {
+                mService.setUserRestrictions(
+                        mService.getDefaultGuestRestrictions(), guest.id);
+            } catch (RemoteException re) {
+                Log.w(TAG, "Could not update guest restrictions");
+            }
         }
         return guest;
     }
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java
index 81f4baf..35da4bc 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java
@@ -96,38 +96,56 @@
     @SmallTest
     public void testsetServiceDataFilter() {
         byte[] setServiceData = new byte[] {
-                0x0b, 0x11, 0x50, 0x64 };
+                0x50, 0x64 };
         ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
         ScanFilter filter = mFilterBuilder.setServiceData(serviceDataUuid, setServiceData).build();
         assertTrue("service data filter fails", filter.matches(mScanResult));
 
-        byte[] nonMatchData = new byte[] {
-                0x0b, 0x01, 0x50, 0x64 };
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData).build();
-        assertFalse("service data filter fails", filter.matches(mScanResult));
+        byte[] emptyData = new byte[0];
+        filter = mFilterBuilder.setServiceData(serviceDataUuid, emptyData).build();
+        assertTrue("service data filter fails", filter.matches(mScanResult));
 
+        byte[] prefixData = new byte[] {
+                0x50 };
+        filter = mFilterBuilder.setServiceData(serviceDataUuid, prefixData).build();
+        assertTrue("service data filter fails", filter.matches(mScanResult));
+
+        byte[] nonMatchData = new byte[] {
+                0x51, 0x64 };
         byte[] mask = new byte[] {
-                (byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF };
+                (byte) 0x00, (byte) 0xFF };
         filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData, mask).build();
         assertTrue("partial service data filter fails", filter.matches(mScanResult));
+
+        filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData).build();
+        assertFalse("service data filter fails", filter.matches(mScanResult));
     }
 
     @SmallTest
     public void testManufacturerSpecificData() {
         byte[] setManufacturerData = new byte[] {
-                (byte) 0xE0, 0x00, 0x02, 0x15 };
-        int manufacturerId = 224;
+                0x02, 0x15 };
+        int manufacturerId = 0xE0;
         ScanFilter filter =
                 mFilterBuilder.setManufacturerData(manufacturerId, setManufacturerData).build();
-        assertTrue("setManufacturerData filter fails", filter.matches(mScanResult));
+        assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
 
+        byte[] emptyData = new byte[0];
+        filter = mFilterBuilder.setManufacturerData(manufacturerId, emptyData).build();
+        assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
+
+        byte[] prefixData = new byte[] {
+                0x02 };
+        filter = mFilterBuilder.setManufacturerData(manufacturerId, prefixData).build();
+        assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
+
+        // Test data mask
         byte[] nonMatchData = new byte[] {
-                (byte) 0xF0, 0x00, 0x02, 0x15 };
+                0x02, 0x14 };
         filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData).build();
-        assertFalse("setManufacturerData filter fails", filter.matches(mScanResult));
-
+        assertFalse("manufacturer data filter fails", filter.matches(mScanResult));
         byte[] mask = new byte[] {
-                (byte) 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF
+                (byte) 0xFF, (byte) 0x00
         };
         filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData, mask).build();
         assertTrue("partial setManufacturerData filter fails", filter.matches(mScanResult));
@@ -153,27 +171,33 @@
                 ParcelUuid.fromString("FFFFFFF0-FFFF-FFFF-FFFF-FFFFFFFFFFFF")).build();
         testReadWriteParcelForFilter(filter);
 
-        byte[] setServiceData = new byte[] {
-                0x0b, 0x11, 0x50, 0x64 };
+        byte[] serviceData = new byte[] {
+                0x50, 0x64 };
 
         ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, setServiceData).build();
+        filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData).build();
+        testReadWriteParcelForFilter(filter);
+
+        filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build();
         testReadWriteParcelForFilter(filter);
 
         byte[] serviceDataMask = new byte[] {
-                (byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF };
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, setServiceData, serviceDataMask)
+                (byte) 0xFF, (byte) 0xFF };
+        filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData, serviceDataMask)
                 .build();
         testReadWriteParcelForFilter(filter);
 
         byte[] manufacturerData = new byte[] {
-                (byte) 0xE0, 0x00, 0x02, 0x15 };
-        int manufacturerId = 224;
+                0x02, 0x15 };
+        int manufacturerId = 0xE0;
         filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData).build();
         testReadWriteParcelForFilter(filter);
 
+        filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build();
+        testReadWriteParcelForFilter(filter);
+
         byte[] manufacturerDataMask = new byte[] {
-                (byte) 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF
+                (byte) 0xFF, (byte) 0xFF
         };
         filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData,
                 manufacturerDataMask).build();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index f1284d80..4b60c9f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -17,6 +17,7 @@
 package com.android.server.devicepolicy;
 
 import android.app.AppGlobals;
+import android.content.ComponentName;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -53,6 +54,7 @@
     private static final String TAG_PROFILE_OWNER = "profile-owner";
     private static final String ATTR_NAME = "name";
     private static final String ATTR_PACKAGE = "package";
+    private static final String ATTR_COMPONENT_NAME = "component";
     private static final String ATTR_USERID = "userId";
 
     private AtomicFile fileForWriting;
@@ -100,6 +102,7 @@
     }
 
     /**
+     * @deprecated Use a component name instead of package name
      * Creates an instance of the device owner object with the profile owner set.
      */
     static DeviceOwner createWithProfileOwner(String packageName, String ownerName, int userId) {
@@ -108,6 +111,15 @@
         return owner;
     }
 
+    /**
+     * Creates an instance of the device owner object with the profile owner set.
+     */
+    static DeviceOwner createWithProfileOwner(ComponentName admin, String ownerName, int userId) {
+        DeviceOwner owner = new DeviceOwner();
+        owner.mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
+        return owner;
+    }
+
     String getDeviceOwnerPackageName() {
         return mDeviceOwner != null ? mDeviceOwner.packageName : null;
     }
@@ -124,19 +136,36 @@
         mDeviceOwner = null;
     }
 
+    /**
+     * @deprecated
+     */
     void setProfileOwner(String packageName, String ownerName, int userId) {
         mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName));
     }
 
+    void setProfileOwner(ComponentName admin, String ownerName, int userId) {
+        mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
+    }
+
     void removeProfileOwner(int userId) {
         mProfileOwners.remove(userId);
     }
 
+    /**
+     * @deprecated Use getProfileOwnerComponent
+     * @param userId
+     * @return
+     */
     String getProfileOwnerPackageName(int userId) {
         OwnerInfo profileOwner = mProfileOwners.get(userId);
         return profileOwner != null ? profileOwner.packageName : null;
     }
 
+    ComponentName getProfileOwnerComponent(int userId) {
+        OwnerInfo profileOwner = mProfileOwners.get(userId);
+        return profileOwner != null ? profileOwner.admin : null;
+    }
+
     String getProfileOwnerName(int userId) {
         OwnerInfo profileOwner = mProfileOwners.get(userId);
         return profileOwner != null ? profileOwner.name : null;
@@ -191,15 +220,23 @@
 
                 String tag = parser.getName();
                 if (tag.equals(TAG_DEVICE_OWNER)) {
-                    mDeviceOwner = new OwnerInfo(
-                            parser.getAttributeValue(null, ATTR_NAME),
-                            parser.getAttributeValue(null, ATTR_PACKAGE));
+                    String name = parser.getAttributeValue(null, ATTR_NAME);
+                    String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+                    mDeviceOwner = new OwnerInfo(name, packageName);
                 } else if (tag.equals(TAG_PROFILE_OWNER)) {
                     String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                     String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
+                    String profileOwnerComponentStr =
+                            parser.getAttributeValue(null, ATTR_COMPONENT_NAME);
                     int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID));
-                    mProfileOwners.put(userId,
-                            new OwnerInfo(profileOwnerName, profileOwnerPackageName));
+                    OwnerInfo profileOwnerInfo;
+                    if (profileOwnerComponentStr != null) {
+                        profileOwnerInfo = new OwnerInfo(profileOwnerName,
+                                ComponentName.unflattenFromString(profileOwnerComponentStr));
+                    } else {
+                        profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName);
+                    }
+                    mProfileOwners.put(userId, profileOwnerInfo);
                 } else {
                     throw new XmlPullParserException(
                             "Unexpected tag in device owner file: " + tag);
@@ -230,9 +267,6 @@
             if (mDeviceOwner != null) {
                 out.startTag(null, TAG_DEVICE_OWNER);
                 out.attribute(null, ATTR_PACKAGE, mDeviceOwner.packageName);
-                if (mDeviceOwner.packageName != null) {
-                    out.attribute(null, ATTR_NAME, mDeviceOwner.packageName);
-                }
                 out.endTag(null, TAG_DEVICE_OWNER);
             }
 
@@ -240,9 +274,13 @@
             if (mProfileOwners.size() > 0) {
                 for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) {
                     out.startTag(null, TAG_PROFILE_OWNER);
-                    out.attribute(null, ATTR_PACKAGE, owner.getValue().packageName);
-                    out.attribute(null, ATTR_NAME, owner.getValue().name);
+                    OwnerInfo ownerInfo = owner.getValue();
+                    out.attribute(null, ATTR_PACKAGE, ownerInfo.packageName);
+                    out.attribute(null, ATTR_NAME, ownerInfo.name);
                     out.attribute(null, ATTR_USERID, Integer.toString(owner.getKey()));
+                    if (ownerInfo.admin != null) {
+                        out.attribute(null, ATTR_COMPONENT_NAME, ownerInfo.admin.flattenToString());
+                    }
                     out.endTag(null, TAG_PROFILE_OWNER);
                 }
             }
@@ -282,10 +320,18 @@
     static class OwnerInfo {
         public String name;
         public String packageName;
+        public ComponentName admin;
 
         public OwnerInfo(String name, String packageName) {
             this.name = name;
             this.packageName = packageName;
+            this.admin = new ComponentName(packageName, "");
+        }
+
+        public OwnerInfo(String name, ComponentName admin) {
+            this.name = name;
+            this.admin = admin;
+            this.packageName = admin.getPackageName();
         }
     }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f49451e..15bea5a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -905,7 +905,8 @@
         for (ActiveAdmin admin : candidates) {
             boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
             boolean ownsProfile = (getProfileOwner(userHandle) != null
-                    && getProfileOwner(userHandle).equals(admin.info.getPackageName()));
+                    && getProfileOwner(userHandle).getPackageName()
+                        .equals(admin.info.getPackageName()));
 
             if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
                 if (ownsDevice) {
@@ -3310,7 +3311,7 @@
     }
 
     @Override
-    public boolean setProfileOwner(String packageName, String ownerName, int userHandle) {
+    public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
         if (!mHasFeature) {
             return false;
         }
@@ -3322,26 +3323,28 @@
                     "Attempted to set profile owner for invalid userId: " + userHandle);
         }
 
-        if (packageName == null
-                || !DeviceOwner.isInstalledForUser(packageName, userHandle)) {
-            throw new IllegalArgumentException("Package name " + packageName
+        if (who == null
+                || !DeviceOwner.isInstalledForUser(who.getPackageName(), userHandle)) {
+            throw new IllegalArgumentException("Component " + who
                     + " not installed for userId:" + userHandle);
         }
         synchronized (this) {
-            if (isUserSetupComplete(userHandle)) {
+            // Only SYSTEM_UID can override the userSetupComplete
+            if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
+                    && isUserSetupComplete(userHandle)) {
                 throw new IllegalStateException(
                         "Trying to set profile owner but user is already set-up.");
             }
 
             if (mDeviceOwner == null) {
                 // Device owner state does not exist, create it.
-                mDeviceOwner = DeviceOwner.createWithProfileOwner(packageName, ownerName,
+                mDeviceOwner = DeviceOwner.createWithProfileOwner(who, ownerName,
                         userHandle);
                 mDeviceOwner.writeOwnerFile();
                 return true;
             } else {
                 // Device owner already exists, update it.
-                mDeviceOwner.setProfileOwner(packageName, ownerName, userHandle);
+                mDeviceOwner.setProfileOwner(who, ownerName, userHandle);
                 mDeviceOwner.writeOwnerFile();
                 return true;
             }
@@ -3349,6 +3352,38 @@
     }
 
     @Override
+    public void clearProfileOwner(ComponentName who) {
+        if (!mHasFeature) {
+            return;
+        }
+        UserHandle callingUser = Binder.getCallingUserHandle();
+        // Check if this is the profile owner who is calling
+        getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        synchronized (this) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                mUserManager.setUserRestrictions(new Bundle(), callingUser);
+                if (mDeviceOwner != null) {
+                    mDeviceOwner.removeProfileOwner(callingUser.getIdentifier());
+                    mDeviceOwner.writeOwnerFile();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    @Override
+    public boolean hasUserSetupCompleted() {
+        if (!mHasFeature) {
+            return true;
+        }
+        DevicePolicyData policy = getUserData(UserHandle.getCallingUserId());
+        // If policy is null, return true, else check if the setup has completed.
+        return policy == null || policy.mUserSetupComplete;
+    }
+
+    @Override
     public void setProfileEnabled(ComponentName who) {
         if (!mHasFeature) {
             return;
@@ -3397,14 +3432,14 @@
     }
 
     @Override
-    public String getProfileOwner(int userHandle) {
+    public ComponentName getProfileOwner(int userHandle) {
         if (!mHasFeature) {
             return null;
         }
 
         synchronized (this) {
             if (mDeviceOwner != null) {
-                return mDeviceOwner.getProfileOwnerPackageName(userHandle);
+                return mDeviceOwner.getProfileOwnerComponent(userHandle);
             }
         }
         return null;
@@ -3413,8 +3448,9 @@
     // Returns the active profile owner for this user or null if the current user has no
     // profile owner.
     private ActiveAdmin getProfileOwnerAdmin(int userHandle) {
-        String profileOwnerPackage = getProfileOwner(userHandle);
-        if (profileOwnerPackage == null) {
+        ComponentName profileOwner =
+                mDeviceOwner != null ? mDeviceOwner.getProfileOwnerComponent(userHandle) : null;
+        if (profileOwner == null) {
             return null;
         }
 
@@ -3422,7 +3458,7 @@
         final int n = policy.mAdminList.size();
         for (int i = 0; i < n; i++) {
             ActiveAdmin admin = policy.mAdminList.get(i);
-            if (profileOwnerPackage.equals(admin.info.getPackageName())) {
+            if (profileOwner.equals(admin.info)) {
                 return admin;
             }
         }
@@ -3800,7 +3836,7 @@
             }
 
             setActiveAdmin(profileOwnerComponent, true, user.getIdentifier(), adminExtras);
-            setProfileOwner(profileOwnerPkg, ownerName, user.getIdentifier());
+            setProfileOwner(profileOwnerComponent, ownerName, user.getIdentifier());
             return user;
         } finally {
             restoreCallingIdentity(id);