Merge "Migrating MmsConfig to CarrierConfigManager." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 8e08df9..a9ae32b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3513,6 +3513,7 @@
     method public deprecated void setTitleColor(int);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
+    method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public boolean shouldUpRecreateTask(android.content.Intent);
     method public final deprecated void showDialog(int);
     method public final deprecated boolean showDialog(int, android.os.Bundle);
@@ -5803,6 +5804,7 @@
     method public void wipeData(int);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
+    field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE = "android.app.action.PROVISION_MANAGED_DEVICE";
     field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
     field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
     field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
@@ -26141,8 +26143,6 @@
     method public static java.lang.String getVersion(android.content.Context);
     field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
     field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
-    field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
-    field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
     field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
     field public static final java.lang.String AUTHORITY = "media";
     field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
@@ -26170,6 +26170,7 @@
     field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
     field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
     field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
+    field public static final java.lang.String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service";
     field public static final java.lang.String UNKNOWN_STRING = "<unknown>";
   }
 
@@ -28728,6 +28729,13 @@
 
 package android.service.media {
 
+  public abstract class CameraPrewarmService extends android.app.Service {
+    ctor public CameraPrewarmService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onCooldown(boolean);
+    method public abstract void onPrewarm();
+  }
+
   public abstract class MediaBrowserService extends android.app.Service {
     ctor public MediaBrowserService();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
@@ -30870,12 +30878,14 @@
 
   public class PhoneNumberUtils {
     ctor public PhoneNumberUtils();
-    method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
+    method public static void addTtsSpan(android.text.Spannable, int, int);
     method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
     method public static java.lang.String calledPartyBCDToString(byte[], int, int);
     method public static boolean compare(java.lang.String, java.lang.String);
     method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
     method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
+    method public static android.text.style.TtsSpan createTtsSpan(java.lang.String);
+    method public static java.lang.CharSequence createTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String extractNetworkPortion(java.lang.String);
     method public static java.lang.String extractPostDialPortion(java.lang.String);
     method public static deprecated void formatJapaneseNumber(android.text.Editable);
@@ -30888,8 +30898,6 @@
     method public static java.lang.String formatNumberToRFC3966(java.lang.String, java.lang.String);
     method public static deprecated int getFormatTypeForLocale(java.util.Locale);
     method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
-    method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
-    method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String getStrippedReversed(java.lang.String);
     method public static final boolean is12Key(char);
     method public static final boolean isDialable(char);
diff --git a/api/system-current.txt b/api/system-current.txt
index e3f6699..d034e80 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3599,6 +3599,7 @@
     method public deprecated void setTitleColor(int);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
+    method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public boolean shouldUpRecreateTask(android.content.Intent);
     method public final deprecated void showDialog(int);
     method public final deprecated boolean showDialog(int, android.os.Bundle);
@@ -5913,6 +5914,7 @@
     method public void wipeData(int);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
+    field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE = "android.app.action.PROVISION_MANAGED_DEVICE";
     field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
     field public static final java.lang.String ACTION_SEND_DEVICE_INITIALIZER_STATUS = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS";
     field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
@@ -28070,8 +28072,6 @@
     method public static java.lang.String getVersion(android.content.Context);
     field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
     field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
-    field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
-    field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
     field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
     field public static final java.lang.String AUTHORITY = "media";
     field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
@@ -28099,6 +28099,7 @@
     field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
     field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
     field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
+    field public static final java.lang.String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service";
     field public static final java.lang.String UNKNOWN_STRING = "<unknown>";
   }
 
@@ -30760,6 +30761,13 @@
 
 package android.service.media {
 
+  public abstract class CameraPrewarmService extends android.app.Service {
+    ctor public CameraPrewarmService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onCooldown(boolean);
+    method public abstract void onPrewarm();
+  }
+
   public abstract class MediaBrowserService extends android.app.Service {
     ctor public MediaBrowserService();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
@@ -33085,12 +33093,14 @@
 
   public class PhoneNumberUtils {
     ctor public PhoneNumberUtils();
-    method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
+    method public static void addTtsSpan(android.text.Spannable, int, int);
     method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
     method public static java.lang.String calledPartyBCDToString(byte[], int, int);
     method public static boolean compare(java.lang.String, java.lang.String);
     method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
     method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
+    method public static android.text.style.TtsSpan createTtsSpan(java.lang.String);
+    method public static java.lang.CharSequence createTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String extractNetworkPortion(java.lang.String);
     method public static java.lang.String extractPostDialPortion(java.lang.String);
     method public static deprecated void formatJapaneseNumber(android.text.Editable);
@@ -33103,8 +33113,6 @@
     method public static java.lang.String formatNumberToRFC3966(java.lang.String, java.lang.String);
     method public static deprecated int getFormatTypeForLocale(java.util.Locale);
     method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
-    method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
-    method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String getStrippedReversed(java.lang.String);
     method public static final boolean is12Key(char);
     method public static final boolean isDialable(char);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 49f5099..966482d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3746,6 +3746,7 @@
      *
      * @see #onRequestPermissionsResult(int, String[], int[])
      * @see #checkSelfPermission(String)
+     * @see #shouldShowRequestPermissionRationale(String)
      */
     public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
         Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
@@ -3770,6 +3771,30 @@
     }
 
     /**
+     * Gets whether you should show UI with rationale for requesting a permission.
+     * You should do this only if you do not have the permission and the context in
+     * which the permission is requested does not clearly communicate to the user
+     * what would be the benefit from granting this permission.
+     * <p>
+     * For example, if you write a camera app, requesting the camera permission
+     * would be expected by the user and no rationale for why it is requested is
+     * needed. If however, the app needs location for tagging photos then a non-tech
+     * savvy user may wonder how location is related to taking photos. In this case
+     * you may choose to show UI with rationale of requesting this permission.
+     * </p>
+     *
+     * @param permission A permission your app wants to request.
+     * @return Whether you can show permission rationale UI.
+     *
+     * @see #checkSelfPermission(String)
+     * @see #requestPermissions(String[], int)
+     * @see #onRequestPermissionsResult(int, String[], int[])
+     */
+    public boolean shouldShowRequestPermissionRationale(String permission) {
+        return getPackageManager().shouldShowRequestPermissionRationale(permission);
+    }
+
+    /**
      * Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
      * with no options.
      *
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 04f6430..41e3db8 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -486,6 +486,16 @@
     }
 
     @Override
+    public boolean shouldShowRequestPermissionRationale(String permission) {
+        try {
+            return mPM.shouldShowRequestPermissionRationale(permission,
+                    mContext.getPackageName(), mContext.getUserId());
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
     public int checkSignatures(String pkg1, String pkg2) {
         try {
             return mPM.checkSignatures(pkg1, pkg2);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a0b95b6..55eaf27 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -130,6 +130,39 @@
         = "android.app.action.PROVISION_MANAGED_PROFILE";
 
     /**
+     * Activity action: Starts the provisioning flow which sets up a managed device.
+     * Must be started with {@link android.app.Activity#startActivityForResult(Intent, int)}.
+     *
+     * <p> During device owner provisioning a device admin app is set as the owner of the device.
+     * A device owner has full control over the device. The device owner can not be modified by the
+     * user.
+     *
+     * <p> A typical use case would be a device that is owned by a company, but used by either an
+     * employee or client.
+     *
+     * <p> An intent with this action can be sent only on an unprovisioned device.
+     * It is possible to check if the device is provisioned or not by looking at
+     * {@link android.provider.Settings.Global#DEVICE_PROVISIONED}
+     *
+     * The intent contains the following extras:
+     * <ul>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
+     * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}, optional</li>
+     * </ul>
+     *
+     * <p> When device owner provisioning has completed, an intent of the type
+     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcast to the
+     * device owner.
+     *
+     * <p> If provisioning fails, the device is factory reset.
+     *
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_PROVISION_MANAGED_DEVICE
+        = "android.app.action.PROVISION_MANAGED_DEVICE";
+
+    /**
      * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
      * a mobile device management application that starts managed profile provisioning to pass data
      * to itself on the managed profile when provisioning completes. The mobile device management
@@ -169,11 +202,13 @@
      * application that will be set as the profile owner or device owner and active admin.
      *
      * <p>If an application starts provisioning directly via an intent with action
-     * {@link #ACTION_PROVISION_MANAGED_PROFILE} the package name of this component has to match the
-     * package name of the application that started provisioning.
+     * {@link #ACTION_PROVISION_MANAGED_PROFILE} or
+     * {@link #ACTION_PROVISION_MANAGED_DEVICE} the package name of this
+     * component has to match the package name of the application that started provisioning.
      *
      * <p>This component is set as device owner and active admin when device owner provisioning is
-     * started by an NFC message containing an NFC record with MIME type
+     * started by an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE} or by an NFC
+     * message containing an NFC record with MIME type
      * {@link #MIME_TYPE_PROVISIONING_NFC_V2}. For the NFC record, the component name should be
      * flattened to a string, via {@link ComponentName#flattenToShortString()}.
      *
@@ -213,8 +248,8 @@
      * A Boolean extra that can be used by the mobile device management application to skip the
      * disabling of system apps during provisioning when set to {@code true}.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
-     * provisioning via an NFC bump.
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} or an intent with action
+     * {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
      */
     public static final String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED =
             "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
@@ -414,8 +449,8 @@
      * A boolean extra indicating whether device encryption can be skipped as part of Device Owner
      * provisioning.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
-     * provisioning via an NFC bump.
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} or an intent with action
+     * {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
      */
     public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
              "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
@@ -609,8 +644,7 @@
      *
      * <p>During device owner provisioning a device admin app is set as the owner of the device.
      * A device owner has full control over the device. The device owner can not be modified by the
-     * user and the only way of resetting the device is if the device owner app calls a factory
-     * reset.
+     * user.
      *
      * <p> A typical use case would be a device that is owned by a company, but used by either an
      * employee or client.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index ddff782..00b8c71 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -105,6 +105,9 @@
     void updatePermissionFlags(String permissionName, String packageName, int flagMask,
             int flagValues, int userId);
 
+    boolean shouldShowRequestPermissionRationale(String permissionName,
+            String packageName, int userId);
+
     boolean isProtectedBroadcast(String actionName);
 
     int checkSignatures(String pkg1, String pkg2);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2ca0306..45245e4 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2539,6 +2539,19 @@
             @NonNull UserHandle user);
 
     /**
+     * Gets whether you should show UI with rationale for requesting a permission.
+     * You should do this only if you do not have the permission and the context in
+     * which the permission is requested does not clearly communicate to the user
+     * what would be the benefit from grating this permission.
+     *
+     * @param permission A permission your app wants to request.
+     * @return Whether you can show permission rationale UI.
+     *
+     * @hide
+     */
+    public abstract boolean shouldShowRequestPermissionRationale(String permission);
+
+    /**
      * Returns an {@link android.content.Intent} suitable for passing to
      * {@link android.app.Activity#startActivityForResult(android.content.Intent, int)}
      * which prompts the user to grant permissions to this application.
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 7565654b..51dbdee3 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -22,6 +22,7 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteException;
@@ -33,6 +34,7 @@
 import android.net.Uri;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.service.media.CameraPrewarmService;
 import android.util.Log;
 
 import java.io.FileInputStream;
@@ -226,33 +228,24 @@
     public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
 
     /**
-     * The name of the Intent action used to indicate that a camera launch might be imminent. This
-     * broadcast should be targeted to the package that is receiving
-     * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
-     * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE}, depending on the context. If such
-     * intent would launch the resolver activity, this broadcast should not be sent at all.
+     * Name under which an activity handling {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
+     * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE} publishes the service name for its prewarm
+     * service.
      * <p>
-     * A receiver of this broadcast should do the absolute minimum amount of work to initialize the
-     * camera in order to reduce startup time in likely case that shortly after an actual camera
-     * launch intent would be sent.
+     * This meta-data should reference the fully qualified class name of the prewarm service
+     * extending {@link CameraPrewarmService}.
      * <p>
-     * In case the actual intent will not be fired, the target package will receive
-     * {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN}. However, it is recommended that the receiver
-     * also implements a timeout to close the camera after receiving this intent, as there is no
-     * guarantee that {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN} will be delivered.
+     * The prewarm service will get bound and receive a prewarm signal
+     * {@link CameraPrewarmService#onPrewarm()} when a camera launch intent fire might be imminent.
+     * An application implementing a prewarm service should do the absolute minimum amount of work
+     * to initialize the camera in order to reduce startup time in likely case that shortly after a
+     * camera launch intent would be sent.
+     * <p>
+     * If the camera launch intent gets fired shortly after, the service will be unbound
+     * asynchronously, without receiving
      */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
-
-    /**
-     * The name of the Intent action used to indicate that an imminent camera launch has been
-     * cancelled by the user. This broadcast should be targeted to the package that has received
-     * {@link #ACTION_STILL_IMAGE_CAMERA_PREWARM}.
-     * <p>
-     * A receiver of this broadcast should close the camera immediately.
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
+    public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE =
+            "android.media.still_image_camera_preview_service";
 
     /**
      * The name of the Intent action used to launch a camera in still image mode
@@ -2268,5 +2261,4 @@
         }
         return null;
     }
-
 }
diff --git a/core/java/android/service/media/CameraPrewarmService.java b/core/java/android/service/media/CameraPrewarmService.java
new file mode 100644
index 0000000..335b00a
--- /dev/null
+++ b/core/java/android/service/media/CameraPrewarmService.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.service.media;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+
+/**
+ * Extend this class to implement a camera prewarm service. See
+ * {@link android.provider.MediaStore#META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE}.
+ */
+public abstract class CameraPrewarmService extends Service {
+
+    /**
+     * Intent action to bind the service as a prewarm service.
+     * @hide
+     */
+    public static final String ACTION_PREWARM =
+            "android.service.media.CameraPrewarmService.ACTION_PREWARM";
+
+    /**
+     * Message sent by the client indicating that the camera intent has been fired.
+     * @hide
+     */
+    public static final int MSG_CAMERA_FIRED = 1;
+
+    private final Handler mHandler = new Handler() {
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_CAMERA_FIRED:
+                    mCameraIntentFired = true;
+                    break;
+                default:
+                    super.handleMessage(msg);
+            }
+        }
+    };
+    private boolean mCameraIntentFired;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (ACTION_PREWARM.equals(intent.getAction())) {
+            onPrewarm();
+            return new Messenger(mHandler).getBinder();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        if (ACTION_PREWARM.equals(intent.getAction())) {
+            onCooldown(mCameraIntentFired);
+        }
+        return false;
+    }
+
+    /**
+     * Called when the camera should be prewarmed.
+     */
+    public abstract void onPrewarm();
+
+    /**
+     * Called when prewarm phase is done, either because the camera launch intent has been fired
+     * at this point or prewarm is no longer needed. A client should close the camera
+     * immediately in the latter case.
+     * <p>
+     * In case the camera launch intent has been fired, there is no guarantee about the ordering
+     * of these two events. Cooldown might happen either before or after the activity has been
+     * created that handles the camera intent.
+     *
+     * @param cameraIntentFired Indicates whether the intent to launch the camera has been
+     *                          fired.
+     */
+    public abstract void onCooldown(boolean cameraIntentFired);
+}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 22c0680..14065b1 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -289,6 +289,8 @@
     private Rect mTempRect;
     private Rect mOutsets = new Rect();
 
+    private boolean mIsStartingWindow;
+
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService("window"));
@@ -3891,7 +3893,7 @@
                 // A pending invalidation will typically be resolved before the posted message
                 // would run normally in order to satisfy instance state restoration.
                 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
-                if (!isDestroyed() && (st == null || st.menu == null)) {
+                if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
                     invalidatePanelMenu(FEATURE_ACTION_BAR);
                 }
             } else {
@@ -4966,4 +4968,8 @@
             mDecor.updateColorViews(null, false /* animate */);
         }
     }
+
+    public void setIsStartingWindow(boolean isStartingWindow) {
+        mIsStartingWindow = isStartingWindow;
+    }
 }
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_hamburger_alpha.png b/packages/DocumentsUI/res/drawable-hdpi/ic_hamburger_alpha.png
index b38e5ee..3f8ebd6 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_hamburger_alpha.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_hamburger_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_delete_alpha.png b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_delete_alpha.png
index b63eecd..dbbb602 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_delete_alpha.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_delete_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_share_alpha.png b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_share_alpha.png
index b7093a0..20ba480 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_share_alpha.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_share_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_hamburger_alpha.png b/packages/DocumentsUI/res/drawable-mdpi/ic_hamburger_alpha.png
index d4f9222..ef2a48c 100644
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_hamburger_alpha.png
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_hamburger_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_menu_delete_alpha.png b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_delete_alpha.png
index 29c9990..999aa4c 100644
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_menu_delete_alpha.png
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_delete_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_menu_share_alpha.png b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_share_alpha.png
index 7008f67..f02d360 100644
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_menu_share_alpha.png
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_share_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_hamburger_alpha.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_hamburger_alpha.png
index aec4d00..4e0286b 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_hamburger_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_hamburger_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_delete_alpha.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_delete_alpha.png
index 2c81000..796ccd2 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_delete_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_delete_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share_alpha.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share_alpha.png
index afb2f3d..81c80b7 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_share_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_hamburger_alpha.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_hamburger_alpha.png
index 6891749..7dae60b 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_hamburger_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_hamburger_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_delete_alpha.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_delete_alpha.png
index c2fbdc4a..6d7cb81 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_delete_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_delete_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share_alpha.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share_alpha.png
index f8a5a1a..784933a 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_share_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_hamburger_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_hamburger_alpha.png
index 13b20c6..5c747ed 100644
--- a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_hamburger_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_hamburger_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_delete_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_delete_alpha.png
index 07a78ed..f2b75c3 100644
--- a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_delete_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_delete_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_share_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_share_alpha.png
index 68831f3..5a8544ce 100644
--- a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_share_alpha.png
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_share_alpha.png
Binary files differ
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 2cf30ba..cd4b24a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -60,6 +60,7 @@
     protected ViewMediatorCallback mViewMediatorCallback;
     protected LockPatternUtils mLockPatternUtils;
     private OnDismissAction mDismissAction;
+    private Runnable mCancelAction;
 
     private final KeyguardUpdateMonitorCallback mUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -126,8 +127,17 @@
      *
      * @param action
      */
-    public void setOnDismissAction(OnDismissAction action) {
+    public void setOnDismissAction(OnDismissAction action, Runnable cancelAction) {
+        if (mCancelAction != null) {
+            mCancelAction.run();
+            mCancelAction = null;
+        }
         mDismissAction = action;
+        mCancelAction = cancelAction;
+    }
+
+    public void cancelDismissAction() {
+        setOnDismissAction(null, null);
     }
 
     @Override
@@ -197,6 +207,7 @@
         if (mDismissAction != null) {
             deferKeyguardDone = mDismissAction.onDismiss();
             mDismissAction = null;
+            mCancelAction = null;
         }
         if (mViewMediatorCallback != null) {
             if (deferKeyguardDone) {
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d96ed96..6af69d2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1034,6 +1034,21 @@
     <!-- Name of quick settings -->
     <string name="quick_settings">Quick Settings</string>
 
+    <!-- Name of status bar -->
+    <string name="status_bar">Status bar</string>
+
+    <!-- Name of the ethernet status bar icon. -->
+    <string name="status_bar_ethernet">Ethernet</string>
+
+    <!-- Name of the alarm status bar icon. -->
+    <string name="status_bar_alarm">Alarm</string>
+
+    <!-- Name of the work status bar icon. -->
+    <string name="status_bar_work">Work profile</string>
+
+    <!-- Name of the airplane status bar icon. -->
+    <string name="status_bar_airplane">Airplane mode</string>
+
     <!-- Description for adding  a quick settings tile -->
     <string name="add_tile">Add tile</string>
 
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 135cc82..4e9a407 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -15,16 +15,61 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/system_ui_tuner">
+    android:title="@string/system_ui_tuner">
 
-        <Preference
-            android:key="qs_tuner"
-            android:title="@string/quick_settings" />
+    <Preference
+        android:key="qs_tuner"
+        android:title="@string/quick_settings" />
 
-        <SwitchPreference
-            android:key="battery_pct"
-            android:title="@string/show_battery_percentage"
-            android:summary="@string/show_battery_percentage_summary"
-            android:persistent="false" />
+    <PreferenceScreen
+        android:title="@string/status_bar" >
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="cast"
+            android:title="@string/quick_settings_cast_title" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="hotspot"
+            android:title="@string/quick_settings_hotspot_label" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="bluetooth"
+            android:title="@string/quick_settings_bluetooth_label" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="zen"
+            android:title="@string/quick_settings_dnd_label" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="alarm_clock"
+            android:title="@string/status_bar_alarm" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="managed_profile"
+            android:title="@string/status_bar_work" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="wifi"
+            android:title="@string/quick_settings_wifi_label" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="ethernet"
+            android:title="@string/status_bar_ethernet" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="mobile"
+            android:title="@string/quick_settings_cellular_detail_title" />
+
+        <com.android.systemui.tuner.StatusBarSwitch
+            android:key="airplane"
+            android:title="@string/status_bar_airplane" />
+
+    </PreferenceScreen>
+
+    <SwitchPreference
+        android:key="battery_pct"
+        android:title="@string/show_battery_percentage"
+        android:summary="@string/show_battery_percentage_summary"
+        android:persistent="false" />
 
 </PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index a66f8ec..02e196e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -18,10 +18,13 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.database.ContentObserver;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -33,6 +36,7 @@
 import android.widget.LinearLayout;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.SecurityController;
@@ -49,6 +53,11 @@
     static final String TAG = "SignalClusterView";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
+    private static final String SLOT_AIRPLANE = "airplane";
+    private static final String SLOT_MOBILE = "mobile";
+    private static final String SLOT_WIFI = "wifi";
+    private static final String SLOT_ETHERNET = "ethernet";
+
     NetworkControllerImpl mNC;
     SecurityController mSC;
 
@@ -81,6 +90,11 @@
     private int mEndPadding;
     private int mEndPaddingNothingVisible;
 
+    private boolean mBlockAirplane;
+    private boolean mBlockMobile;
+    private boolean mBlockWifi;
+    private boolean mBlockEthernet;
+
     public SignalClusterView(Context context) {
         this(context, null);
     }
@@ -91,6 +105,14 @@
 
     public SignalClusterView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+        readBlacklist();
+    }
+
+    private void readBlacklist() {
+        mBlockAirplane = StatusBarIconController.isBlocked(getContext(), SLOT_AIRPLANE);
+        mBlockMobile = StatusBarIconController.isBlocked(getContext(), SLOT_MOBILE);
+        mBlockWifi = StatusBarIconController.isBlocked(getContext(), SLOT_WIFI);
+        mBlockEthernet = StatusBarIconController.isBlocked(getContext(), SLOT_ETHERNET);
     }
 
     public void setNetworkController(NetworkControllerImpl nc) {
@@ -141,6 +163,9 @@
 
         apply();
         applyIconTint();
+        getContext().getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(StatusBarIconController.ICON_BLACKLIST), false,
+                mBlacklistObserver);
     }
 
     @Override
@@ -153,6 +178,7 @@
         mAirplane       = null;
         mMobileSignalGroup.removeAllViews();
         mMobileSignalGroup = null;
+        getContext().getContentResolver().unregisterContentObserver(mBlacklistObserver);
 
         super.onDetachedFromWindow();
     }
@@ -172,7 +198,7 @@
     @Override
     public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
             boolean activityIn, boolean activityOut, String description) {
-        mWifiVisible = statusIcon.visible;
+        mWifiVisible = statusIcon.visible && !mBlockWifi;
         mWifiStrengthId = statusIcon.icon;
         mWifiDescription = statusIcon.contentDescription;
 
@@ -184,7 +210,7 @@
             int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
             String description, boolean isWide, int subId) {
         PhoneState state = getOrInflateState(subId);
-        state.mMobileVisible = statusIcon.visible;
+        state.mMobileVisible = statusIcon.visible && !mBlockMobile;
         state.mMobileStrengthId = statusIcon.icon;
         state.mMobileTypeId = statusType;
         state.mMobileDescription = statusIcon.contentDescription;
@@ -196,7 +222,7 @@
 
     @Override
     public void setEthernetIndicators(IconState state) {
-        mEthernetVisible = state.visible;
+        mEthernetVisible = state.visible && !mBlockEthernet;
         mEthernetIconId = state.icon;
         mEthernetDescription = state.contentDescription;
 
@@ -205,7 +231,7 @@
 
     @Override
     public void setNoSims(boolean show) {
-        mNoSimsVisible = show;
+        mNoSimsVisible = show && !mBlockMobile;
     }
 
     @Override
@@ -244,7 +270,7 @@
 
     @Override
     public void setIsAirplaneMode(IconState icon) {
-        mIsAirplaneMode = icon.visible;
+        mIsAirplaneMode = icon.visible && !mBlockAirplane;
         mAirplaneIconId = icon.icon;
         mAirplaneContentDescription = icon.contentDescription;
 
@@ -502,5 +528,14 @@
             setTint(mMobileType, tint);
         }
     }
+
+    private final ContentObserver mBlacklistObserver = new ContentObserver(new Handler()) {
+        public void onChange(boolean selfChange) {
+            readBlacklist();
+            // Re-register to get new callbacks.
+            mNC.removeSignalCallback(SignalClusterView.this);
+            mNC.addSignalCallback(SignalClusterView.this);
+        };
+    };
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 3294e15..baac8ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -18,7 +18,6 @@
 
 import android.app.Notification;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -49,10 +48,17 @@
     private int mNumberY;
     private String mNumberText;
     private Notification mNotification;
+    private final boolean mBlocked;
 
     public StatusBarIconView(Context context, String slot, Notification notification) {
+        this(context, slot, notification, false);
+    }
+
+    public StatusBarIconView(Context context, String slot, Notification notification,
+            boolean blocked) {
         super(context);
         final Resources res = context.getResources();
+        mBlocked = blocked;
         mSlot = slot;
         mNumberPain = new Paint();
         mNumberPain.setTextAlign(Paint.Align.CENTER);
@@ -80,6 +86,7 @@
 
     public StatusBarIconView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mBlocked = false;
         final Resources res = context.getResources();
         final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
         final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
@@ -148,7 +155,7 @@
             invalidate();
         }
         if (!visibilityEquals) {
-            setVisibility(icon.visible ? VISIBLE : GONE);
+            setVisibility(icon.visible && !mBlocked ? VISIBLE : GONE);
         }
         return true;
     }
@@ -281,4 +288,8 @@
         return "StatusBarIconView(slot=" + mSlot + " icon=" + mIcon
             + " notification=" + mNotification + ")";
     }
+
+    public String getSlot() {
+        return mSlot;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index ee5eb38..9ef320bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -24,6 +24,11 @@
  * Keyguard.
  */
 public interface ActivityStarter {
-    public void startActivity(Intent intent, boolean dismissShade);
+    void startActivity(Intent intent, boolean dismissShade);
+    void startActivity(Intent intent, boolean dismissShade, Callback callback);
     void preventNextAnimation();
+
+    interface Callback {
+        void onActivityStarted(int resultCode);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 8bffdc9..64735ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -160,7 +160,7 @@
                 } else {
                     mTouchSlopExeeded = false;
                 }
-                mCallback.onSwipingStarted(targetView == mLeftIcon);
+                mCallback.onSwipingStarted(targetView == mRightIcon);
                 mSwipingInProgress = true;
                 mTargetedView = targetView;
                 mInitialTouchX = x;
@@ -550,7 +550,7 @@
 
         float getMaxTranslationDistance();
 
-        void onSwipingStarted(boolean isRightwardMotion);
+        void onSwipingStarted(boolean rightIcon);
 
         void onSwipingAborted();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index adee5a8..3258a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -16,12 +16,17 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.Application;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
@@ -29,9 +34,13 @@
 import android.graphics.drawable.InsetDrawable;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.MediaStore;
+import android.service.media.CameraPrewarmService;
 import android.telecom.TelecomManager;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -100,7 +109,23 @@
     private PhoneStatusBar mPhoneStatusBar;
 
     private final Interpolator mLinearOutSlowInInterpolator;
-    private boolean mPrewarmSent;
+    private boolean mPrewarmBound;
+    private Messenger mPrewarmMessenger;
+    private final ServiceConnection mPrewarmConnection = new ServiceConnection() {
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            mPrewarmMessenger = new Messenger(service);
+            mPrewarmBound = true;
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mPrewarmBound = false;
+            mPrewarmMessenger = null;
+        }
+    };
+
     private boolean mLeftIsVoiceAssist;
     private AssistManager mAssistManager;
 
@@ -343,37 +368,44 @@
         mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
     }
 
-    public void prewarmCamera() {
+    public void bindCameraPrewarmService() {
         Intent intent = getCameraIntent();
-        String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
+        ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent,
                 KeyguardUpdateMonitor.getCurrentUser());
-        if (targetPackage != null) {
-            Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM);
-            prewarm.setPackage(targetPackage);
-            mPrewarmSent = true;
-            mContext.sendBroadcast(prewarm);
+        if (targetInfo != null) {
+            String clazz = targetInfo.metaData.getString(
+                    MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
+            if (clazz != null) {
+                Intent serviceIntent = new Intent();
+                serviceIntent.setClassName(targetInfo.packageName, clazz);
+                serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
+                try {
+                    getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
+                            Context.BIND_AUTO_CREATE, new UserHandle(UserHandle.USER_CURRENT));
+                } catch (SecurityException e) {
+                    Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName
+                            + " class=" + clazz, e);
+                }
+            }
         }
     }
 
-    public void maybeCooldownCamera() {
-        if (!mPrewarmSent) {
-            return;
-        }
-        mPrewarmSent = false;
-        Intent intent = getCameraIntent();
-        String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
-                KeyguardUpdateMonitor.getCurrentUser());
-        if (targetPackage != null) {
-            Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN);
-            prewarm.setPackage(targetPackage);
-            mContext.sendBroadcast(prewarm);
+    public void unbindCameraPrewarmService(boolean launched) {
+        if (mPrewarmBound) {
+            if (launched) {
+                try {
+                    mPrewarmMessenger.send(Message.obtain(null /* handler */,
+                            CameraPrewarmService.MSG_CAMERA_FIRED));
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Error sending camera fired message", e);
+                }
+            }
+            mContext.unbindService(mPrewarmConnection);
+            mPrewarmBound = false;
         }
     }
 
     public void launchCamera() {
-
-        // Reset prewarm state.
-        mPrewarmSent = false;
         final Intent intent = getCameraIntent();
         boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
                 mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
@@ -381,18 +413,47 @@
             AsyncTask.execute(new Runnable() {
                 @Override
                 public void run() {
-                    mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                    int result = ActivityManager.START_CANCELED;
+                    try {
+                        result = ActivityManagerNative.getDefault().startActivityAsUser(
+                                null, getContext().getBasePackageName(),
+                                intent,
+                                intent.resolveTypeIfNeeded(getContext().getContentResolver()),
+                                null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null,
+                                UserHandle.CURRENT.getIdentifier());
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Unable to start camera activity", e);
+                    }
                     mActivityStarter.preventNextAnimation();
+                    final boolean launched = isSuccessfulLaunch(result);
+                    post(new Runnable() {
+                        @Override
+                        public void run() {
+                            unbindCameraPrewarmService(launched);
+                        }
+                    });
                 }
             });
         } else {
 
             // We need to delay starting the activity because ResolverActivity finishes itself if
             // launched behind lockscreen.
-            mActivityStarter.startActivity(intent, false /* dismissShade */);
+            mActivityStarter.startActivity(intent, false /* dismissShade */,
+                    new ActivityStarter.Callback() {
+                        @Override
+                        public void onActivityStarted(int resultCode) {
+                            unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));
+                        }
+                    });
         }
     }
 
+    private static boolean isSuccessfulLaunch(int result) {
+        return result == ActivityManager.START_SUCCESS
+                || result == ActivityManager.START_DELIVERED_TO_TOP
+                || result == ActivityManager.START_TASK_TO_FRONT;
+    }
+
     public void launchLeftAffordance() {
         if (mLeftIsVoiceAssist) {
             launchVoiceAssist();
@@ -412,8 +473,8 @@
         if (mPhoneStatusBar.isKeyguardCurrentlySecure()) {
             AsyncTask.execute(runnable);
         } else {
-            mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, false /* dismissShade */,
-                    false /* afterKeyguardGone */);
+            mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
+                    false /* dismissShade */, false /* afterKeyguardGone */);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 262d955..3d57d54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -95,16 +95,16 @@
         mShowingSoon = false;
     }
 
-    public void showWithDismissAction(OnDismissAction r) {
+    public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
         ensureView();
-        mKeyguardView.setOnDismissAction(r);
+        mKeyguardView.setOnDismissAction(r, cancelAction);
         show(false /* resetSecuritySelection */);
     }
 
     public void hide(boolean destroyView) {
         cancelShowRunnable();
          if (mKeyguardView != null) {
-            mKeyguardView.setOnDismissAction(null);
+            mKeyguardView.cancelDismissAction();
             mKeyguardView.cleanUp();
         }
         if (destroyView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 5d48190..2fe98bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1934,12 +1934,12 @@
     }
 
     @Override
-    public void onSwipingStarted(boolean isRightwardMotion) {
-        boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? isRightwardMotion
-                : !isRightwardMotion;
-        if (!start) {
+    public void onSwipingStarted(boolean rightIcon) {
+        boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon
+                : rightIcon;
+        if (camera) {
             mSecureCameraLaunchManager.onSwipingStarted();
-            mKeyguardBottomArea.prewarmCamera();
+            mKeyguardBottomArea.bindCameraPrewarmService();
         }
         requestDisallowInterceptTouchEvent(true);
         mOnlyAffordanceInThisMotion = true;
@@ -1948,7 +1948,7 @@
 
     @Override
     public void onSwipingAborted() {
-        mKeyguardBottomArea.maybeCooldownCamera();
+        mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 5ff4ddb..bc95743 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1830,6 +1830,11 @@
     }
 
     @Override
+    public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
+        startActivityDismissingKeyguard(intent, false, dismissShade, callback);
+    }
+
+    @Override
     public void preventNextAnimation() {
         overrideActivityPendingAppTransition(true /* keyguardShowing */);
     }
@@ -2711,7 +2716,12 @@
     }
 
     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
-            final boolean dismissShade) {
+            boolean dismissShade) {
+        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */);
+    }
+
+    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
+            final boolean dismissShade, final Callback callback) {
         if (onlyProvisioned && !isDeviceProvisioned()) return;
 
         final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
@@ -2721,16 +2731,35 @@
             public void run() {
                 intent.setFlags(
                         Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                mContext.startActivityAsUser(
-                        intent, new UserHandle(UserHandle.USER_CURRENT));
+                int result = ActivityManager.START_CANCELED;
+                try {
+                    result = ActivityManagerNative.getDefault().startActivityAsUser(
+                            null, mContext.getBasePackageName(),
+                            intent,
+                            intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                            null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null,
+                            UserHandle.CURRENT.getIdentifier());
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Unable to start activity", e);
+                }
                 overrideActivityPendingAppTransition(
                         keyguardShowing && !afterKeyguardGone);
+                if (callback != null) {
+                    callback.onActivityStarted(result);
+                }
             }
         };
-        executeRunnableDismissingKeyguard(runnable, dismissShade, afterKeyguardGone);
+        Runnable cancelRunnable = new Runnable() {
+            @Override
+            public void run() {
+                callback.onActivityStarted(ActivityManager.START_CANCELED);
+            }
+        };
+        executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, afterKeyguardGone);
     }
 
     public void executeRunnableDismissingKeyguard(final Runnable runnable,
+            final Runnable cancelAction,
             final boolean dismissShade,
             final boolean afterKeyguardGone) {
         final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
@@ -2757,7 +2786,7 @@
                 }
                 return true;
             }
-        }, afterKeyguardGone);
+        }, cancelAction, afterKeyguardGone);
     }
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -2817,10 +2846,15 @@
     }
 
     @Override
-    protected void dismissKeyguardThenExecute(final OnDismissAction action,
+    protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
+        dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
+    }
+
+    private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
             boolean afterKeyguardGone) {
         if (mStatusBarKeyguardViewManager.isShowing()) {
-            mStatusBarKeyguardViewManager.dismissWithAction(action, afterKeyguardGone);
+            mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+                    afterKeyguardGone);
         } else {
             action.onDismiss();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 45da297..a268077 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -20,10 +20,14 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.database.ContentObserver;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArraySet;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.animation.AnimationUtils;
@@ -53,6 +57,8 @@
 
     public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
 
+    public static final String ICON_BLACKLIST = "icon_blacklist";
+
     private Context mContext;
     private PhoneStatusBar mPhoneStatusBar;
     private Interpolator mLinearOutSlowIn;
@@ -89,6 +95,8 @@
     private long mTransitionDeferringStartTime;
     private long mTransitionDeferringDuration;
 
+    private final ArraySet<String> mIconBlacklist;
+
     private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
         @Override
         public void run() {
@@ -118,7 +126,12 @@
         mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
         mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
         mHandler = new Handler();
+        mIconBlacklist = getIconBlacklist(context);
         updateResources();
+
+        context.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(StatusBarIconController.ICON_BLACKLIST), false,
+                mBlacklistObserver);
     }
 
     public void updateResources() {
@@ -130,11 +143,12 @@
     }
 
     public void addSystemIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
-        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
+        boolean blocked = mIconBlacklist.contains(slot);
+        StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
         view.set(icon);
         mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(
                 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
-        view = new StatusBarIconView(mContext, slot, null);
+        view = new StatusBarIconView(mContext, slot, null, blocked);
         view.set(icon);
         mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
                 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
@@ -414,4 +428,43 @@
         }
         mTransitionPending = false;
     }
+
+    private final ContentObserver mBlacklistObserver = new ContentObserver(new Handler()) {
+        public void onChange(boolean selfChange) {
+            mIconBlacklist.clear();
+            mIconBlacklist.addAll(getIconBlacklist(mContext));
+            ArrayList<StatusBarIconView> views = new ArrayList<StatusBarIconView>();
+            // Get all the current views.
+            for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
+                views.add((StatusBarIconView) mStatusIcons.getChildAt(i));
+            }
+            // Remove all the icons.
+            for (int i = views.size() - 1; i >= 0; i--) {
+                removeSystemIcon(views.get(i).getSlot(), i, i);
+            }
+            // Add them all back
+            for (int i = 0; i < views.size(); i++) {
+                addSystemIcon(views.get(i).getSlot(), i, i, views.get(i).getStatusBarIcon());
+            }
+        }
+    };
+
+    public static ArraySet<String> getIconBlacklist(Context context) {
+        String blackListStr = Settings.Secure.getString(context.getContentResolver(),
+                ICON_BLACKLIST);
+        ArraySet<String> ret = new ArraySet<String>();
+        if (blackListStr != null) {
+            String[] blacklist = blackListStr.split(",");
+            for (String slot : blacklist) {
+                if (!TextUtils.isEmpty(slot)) {
+                    ret.add(slot);
+                }
+            }
+        }
+        return ret;
+    }
+
+    public static boolean isBlocked(Context context, String slot) {
+        return getIconBlacklist(context).contains(slot);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 0caf51a..6cb890a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -126,10 +126,11 @@
         updateStates();
     }
 
-    public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) {
+    public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
+            boolean afterKeyguardGone) {
         if (mShowing) {
             if (!afterKeyguardGone) {
-                mBouncer.showWithDismissAction(r);
+                mBouncer.showWithDismissAction(r, cancelAction);
             } else {
                 mBouncer.show(false /* resetSecuritySelection */);
                 mAfterKeyguardGoneAction = r;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index 4269c19..93d0ec3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -19,6 +19,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
@@ -138,14 +139,14 @@
 
     public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
             int currentUserId) {
-        return getTargetPackage(ctx, intent, currentUserId) == null;
+        return getTargetActivityInfo(ctx, intent, currentUserId) == null;
     }
 
     /**
-     * @return the target package of the intent it resolves to a specific package or {@code null} if
-     *         it resolved to the resolver activity
+     * @return the target activity info of the intent it resolves to a specific package or
+     *         {@code null} if it resolved to the resolver activity
      */
-    public static String getTargetPackage(Context ctx, Intent intent,
+    public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent,
             int currentUserId) {
         PackageManager packageManager = ctx.getPackageManager();
         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
@@ -158,7 +159,7 @@
         if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
             return null;
         } else {
-            return resolved.activityInfo.packageName;
+            return resolved.activityInfo;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
index 90c1897..9f593fc 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
@@ -22,6 +22,7 @@
 import android.content.DialogInterface;
 import android.os.Bundle;
 import android.provider.Settings.Secure;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.DragEvent;
 import android.view.LayoutInflater;
@@ -32,7 +33,6 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnDragListener;
-import android.view.View.OnLongClickListener;
 import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.widget.EditText;
@@ -47,6 +47,7 @@
 import com.android.systemui.qs.QSTileView;
 import com.android.systemui.qs.tiles.IntentTile;
 import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.policy.SecurityController;
 
 import java.util.List;
 
@@ -174,7 +175,7 @@
 
         public CustomHost(Context context) {
             super(context, null, null, null, null, null, null, null, null, null,
-                    null, null, null);
+                    null, null, new BlankSecurityController());
         }
 
         @Override
@@ -215,15 +216,8 @@
         }
 
         private void setTiles(List<String> tiles) {
-            StringBuilder builder = new StringBuilder();
-            for (int i = 0; i < tiles.size(); i++) {
-                if (builder.length() != 0) {
-                    builder.append(',');
-                }
-                builder.append(tiles.get(i));
-            }
-            Secure.putStringForUser(getContext().getContentResolver(),
-                    TILES_SETTING, builder.toString(), mUserTracker.getCurrentUserId());
+            Secure.putStringForUser(getContext().getContentResolver(), TILES_SETTING,
+                    TextUtils.join(",", tiles), mUserTracker.getCurrentUserId());
         }
 
         public void showAddDialog() {
@@ -282,6 +276,45 @@
             }
             return true;
         }
+
+        private static class BlankSecurityController implements SecurityController {
+            @Override
+            public boolean hasDeviceOwner() {
+                return false;
+            }
+
+            @Override
+            public boolean hasProfileOwner() {
+                return false;
+            }
+
+            @Override
+            public String getDeviceOwnerName() {
+                return null;
+            }
+
+            @Override
+            public String getProfileOwnerName() {
+                return null;
+            }
+
+            @Override
+            public boolean isVpnEnabled() {
+                return false;
+            }
+
+            @Override
+            public void onUserSwitched(int newUserId) {
+            }
+
+            @Override
+            public void addCallback(SecurityControllerCallback callback) {
+            }
+
+            @Override
+            public void removeCallback(SecurityControllerCallback callback) {
+            }
+        }
     }
 
     private static class DraggableTile extends QSTile<QSTile.State>
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
new file mode 100644
index 0000000..8158a68
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.tuner;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+
+import java.util.Set;
+
+public class StatusBarSwitch extends SwitchPreference {
+
+    public StatusBarSwitch(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setChecked(!StatusBarIconController.isBlocked(getContext(), getKey()));
+    }
+
+    @Override
+    protected boolean persistBoolean(boolean value) {
+        Set<String> blacklist = StatusBarIconController.getIconBlacklist(getContext());
+        if (!value) {
+            // If not enabled add to blacklist.
+            if (!blacklist.contains(getKey())) {
+                blacklist.add(getKey());
+                setList(blacklist);
+            }
+        } else {
+            if (blacklist != null && blacklist.remove(getKey())) {
+                setList(blacklist);
+            }
+        }
+        return true;
+    }
+
+    private void setList(Set<String> blacklist) {
+        ContentResolver contentResolver = getContext().getContentResolver();
+        Settings.Secure.putString(contentResolver, StatusBarIconController.ICON_BLACKLIST,
+                TextUtils.join(",", blacklist));
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9b619c7..47e3963 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3360,6 +3360,46 @@
     }
 
     @Override
+    public boolean shouldShowRequestPermissionRationale(String permissionName,
+            String packageName, int userId) {
+        if (UserHandle.getCallingUserId() != userId) {
+            mContext.enforceCallingPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "canShowRequestPermissionRationale for user " + userId);
+        }
+
+        final int uid = getPackageUid(packageName, userId);
+        if (UserHandle.getAppId(getCallingUid()) != UserHandle.getAppId(uid)) {
+            return false;
+        }
+
+        if (checkPermission(permissionName, packageName, userId)
+                == PackageManager.PERMISSION_GRANTED) {
+            return false;
+        }
+
+        final int flags;
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            flags = getPermissionFlags(permissionName,
+                    packageName, userId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+
+        final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
+                | PackageManager.FLAG_PERMISSION_POLICY_FIXED
+                | PackageManager.FLAG_PERMISSION_USER_FIXED;
+
+        if ((flags & fixedFlags) != 0) {
+            return false;
+        }
+
+        return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
+    }
+
+    @Override
     public boolean isProtectedBroadcast(String actionName) {
         synchronized (mPackages) {
             return mProtectedBroadcasts.contains(actionName);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c8397e2..b8d0692 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2154,7 +2154,8 @@
                 }
             }
 
-            Window win = new PhoneWindow(context);
+            PhoneWindow win = new PhoneWindow(context);
+            win.setIsStartingWindow(true);
             final TypedArray ta = win.getWindowStyle();
             if (ta.getBoolean(
                         com.android.internal.R.styleable.Window_windowDisablePreview, false)
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 2feb380..52c60e6 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -635,7 +635,7 @@
      *         ringback tone on its behalf.
      */
     public boolean isRingbackRequested() {
-        return false;
+        return mRingbackRequested;
     }
 
     /**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index a41875f..3fcd7d9 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2336,12 +2336,12 @@
      * @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
      * @return A {@code CharSequence} with appropriate annotations.
      */
-    public static CharSequence getPhoneTtsSpannable(CharSequence phoneNumber) {
+    public static CharSequence createTtsSpannable(CharSequence phoneNumber) {
         if (phoneNumber == null) {
             return null;
         }
         Spannable spannable = Spannable.Factory.getInstance().newSpannable(phoneNumber);
-        PhoneNumberUtils.addPhoneTtsSpan(spannable, 0, spannable.length());
+        PhoneNumberUtils.addTtsSpan(spannable, 0, spannable.length());
         return spannable;
     }
 
@@ -2353,8 +2353,8 @@
      * @param start The starting character position of the phone number in {@code s}.
      * @param endExclusive The position after the ending character in the phone number {@code s}.
      */
-    public static void addPhoneTtsSpan(Spannable s, int start, int endExclusive) {
-        s.setSpan(getPhoneTtsSpan(s.subSequence(start, endExclusive).toString()),
+    public static void addTtsSpan(Spannable s, int start, int endExclusive) {
+        s.setSpan(createTtsSpan(s.subSequence(start, endExclusive).toString()),
                 start,
                 endExclusive,
                 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -2366,13 +2366,13 @@
      *
      * @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
      * @return A {@code CharSequence} with appropriate annotations.
-     * @deprecated Renamed {@link #getPhoneTtsSpannable}.
+     * @deprecated Renamed {@link #createTtsSpannable}.
      *
      * @hide
      */
     @Deprecated
     public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
-        return getPhoneTtsSpannable(phoneNumber);
+        return createTtsSpannable(phoneNumber);
     }
 
     /**
@@ -2383,13 +2383,13 @@
      * @param start The starting character position of the phone number in {@code s}.
      * @param end The ending character position of the phone number in {@code s}.
      *
-     * @deprecated Renamed {@link #addPhoneTtsSpan}.
+     * @deprecated Renamed {@link #addTtsSpan}.
      *
      * @hide
      */
     @Deprecated
     public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
-        addPhoneTtsSpan(s, start, end);
+        addTtsSpan(s, start, end);
     }
 
     /**
@@ -2398,7 +2398,7 @@
      * @param phoneNumberString A {@code String} the entirety of which represents a phone number.
      * @return A {@code TtsSpan} for {@param phoneNumberString}.
      */
-    public static TtsSpan getPhoneTtsSpan(String phoneNumberString) {
+    public static TtsSpan createTtsSpan(String phoneNumberString) {
         if (phoneNumberString == null) {
             return null;
         }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index bf1ea4d..3b7aa9f 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -218,6 +218,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public boolean shouldShowRequestPermissionRationale(String permission) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public int checkSignatures(String pkg1, String pkg2) {
         throw new UnsupportedOperationException();
diff --git a/tests/CameraPrewarmTest/AndroidManifest.xml b/tests/CameraPrewarmTest/AndroidManifest.xml
index eb40200..11b2686 100644
--- a/tests/CameraPrewarmTest/AndroidManifest.xml
+++ b/tests/CameraPrewarmTest/AndroidManifest.xml
@@ -22,13 +22,13 @@
         <activity android:name=".CameraActivity"
                 android:theme="@android:style/Theme.NoTitleBar">
             <intent-filter>
-                <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter>
                 <action android:name="android.media.action.STILL_IMAGE_CAMERA" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
+            <meta-data
+                android:name="android.media.still_image_camera_preview_service"
+                android:value="com.google.android.test.cameraprewarm.PrewarmService">
+            </meta-data>
         </activity>
 
         <activity android:name=".SecureCameraActivity"
@@ -37,16 +37,15 @@
                 <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
+            <meta-data
+                android:name="android.media.still_image_camera_preview_service"
+                android:value="com.google.android.test.cameraprewarm.PrewarmService">
+            </meta-data>
         </activity>
 
-        <receiver android:name=".PrewarmReceiver" >
-            <intent-filter>
-                <action android:name="android.media.action.STILL_IMAGE_CAMERA_PREWARM" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.media.action.STILL_IMAGE_CAMERA_COOLDOWN" />
-            </intent-filter>
-        </receiver>
+        <service android:name=".PrewarmService"
+            android:exported="true">
+        </service>
 
     </application>
 </manifest>
diff --git a/tests/CameraPrewarmTest/res/values/strings.xml b/tests/CameraPrewarmTest/res/values/strings.xml
index 11f7ac7..fe39ac1 100644
--- a/tests/CameraPrewarmTest/res/values/strings.xml
+++ b/tests/CameraPrewarmTest/res/values/strings.xml
@@ -16,6 +16,6 @@
   -->
 
 <resources>
-    <string name="activity_title">Assistant</string>
+    <string name="activity_title">Camera Prewarm test</string>
     <string name="search_label">Orilla Search Engine</string>
 </resources>
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
index 4d22234..0b43666 100644
--- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
-import android.view.WindowManager;
 
 import com.google.android.test.cameraprewarm.R;
 
@@ -31,7 +30,6 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.camera_activity);
-        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
         Log.i(TAG, "Activity created");
     }
 }
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java
deleted file mode 100644
index d49f96d..0000000
--- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.google.android.test.cameraprewarm;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.MediaStore;
-import android.util.Log;
-
-public class PrewarmReceiver extends BroadcastReceiver {
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM)) {
-            Log.i(CameraActivity.TAG, "Prewarm received");
-        } else if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN)){
-            Log.i(CameraActivity.TAG, "Cooldown received");
-        }
-    }
-}
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java
new file mode 100644
index 0000000..d080b1a
--- /dev/null
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.google.android.test.cameraprewarm;
+
+import android.service.media.CameraPrewarmService;
+import android.util.Log;
+
+public class PrewarmService extends CameraPrewarmService {
+
+    @Override
+    public void onPrewarm() {
+        Log.i("PrewarmService", "Warming up");
+    }
+
+    @Override
+    public void onCooldown(boolean cameraIntentFired) {
+        Log.i("PrewarmService", "Cooling down fired=" + cameraIntentFired);
+    }
+}