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);
+ }
+}