Merge "Create ListPopupWindow handler against main looper" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 7891c71..a0dccd5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15863,6 +15863,10 @@
ctor public MediaDrmException(java.lang.String);
}
+ public class MediaDrmResetException extends java.lang.IllegalStateException {
+ ctor public MediaDrmResetException(java.lang.String);
+ }
+
public final class MediaExtractor {
ctor public MediaExtractor();
method public boolean advance();
@@ -30620,6 +30624,7 @@
field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
+ field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
@@ -30677,6 +30682,9 @@
field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
+ field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
+ field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+ field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -31240,6 +31248,8 @@
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
+ field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
}
@@ -34569,6 +34579,7 @@
method public abstract void invalidate();
method public void invalidateContentRect();
method public boolean isTitleOptional();
+ method public void onWindowFocusChanged(boolean);
method public abstract void setCustomView(android.view.View);
method public abstract void setSubtitle(java.lang.CharSequence);
method public abstract void setSubtitle(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index aa6f828..7e3e051 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -17118,6 +17118,10 @@
ctor public MediaDrmException(java.lang.String);
}
+ public class MediaDrmResetException extends java.lang.IllegalStateException {
+ ctor public MediaDrmResetException(java.lang.String);
+ }
+
public final class MediaExtractor {
ctor public MediaExtractor();
method public boolean advance();
@@ -32843,6 +32847,7 @@
field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
+ field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
@@ -32900,6 +32905,9 @@
field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
+ field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
+ field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+ field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -33512,6 +33520,8 @@
field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
field public static final int SIM_STATE_READY = 5; // 0x5
field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+ field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
+ field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
}
@@ -36850,6 +36860,7 @@
method public abstract void invalidate();
method public void invalidateContentRect();
method public boolean isTitleOptional();
+ method public void onWindowFocusChanged(boolean);
method public abstract void setCustomView(android.view.View);
method public abstract void setSubtitle(java.lang.CharSequence);
method public abstract void setSubtitle(int);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 1461380..e178087 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -35,6 +35,9 @@
import android.os.IBinder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
+import android.os.TransactionTooLargeException;
+import android.util.Log;
+
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
@@ -921,8 +924,13 @@
info.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeInt(processState);
- mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
+ try {
+ mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
+ IBinder.FLAG_ONEWAY);
+ } catch (TransactionTooLargeException e) {
+ Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
+ throw e;
+ }
data.recycle();
}
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 08c5236..d83dfc5 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1480,7 +1480,11 @@
* Write the contents of the IntentFilter as an XML stream.
*/
public void writeToXml(XmlSerializer serializer) throws IOException {
- serializer.attribute(null, AUTO_VERIFY_STR, Boolean.toString(getAutoVerify()));
+
+ if (getAutoVerify()) {
+ serializer.attribute(null, AUTO_VERIFY_STR, Boolean.toString(true));
+ }
+
int N = countActions();
for (int i=0; i<N; i++) {
serializer.startTag(null, ACTION_STR);
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 649fdb4..7bab35c 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -45,7 +45,7 @@
* {@link #providerInfo} will be non-null.
*/
public ActivityInfo activityInfo;
-
+
/**
* The service that corresponds to this resolution match, if this resolution
* is for a service. Exactly one of {@link #activityInfo},
@@ -64,21 +64,21 @@
* The IntentFilter that was matched for this ResolveInfo.
*/
public IntentFilter filter;
-
+
/**
* The declared priority of this match. Comes from the "priority"
* attribute or, if not set, defaults to 0. Higher values are a higher
* priority.
*/
public int priority;
-
+
/**
* Order of result according to the user's preference. If the user
* has not set a preference for this result, the value is 0; higher
* values are a higher priority.
*/
public int preferredOrder;
-
+
/**
* The system's evaluation of how well the activity matches the
* IntentFilter. This is a match constant, a combination of
@@ -86,7 +86,7 @@
* and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}.
*/
public int match;
-
+
/**
* Only set when returned by
* {@link PackageManager#queryIntentActivityOptions}, this tells you
@@ -94,29 +94,30 @@
* first in the list, < 0 means it came from the generic Intent query.
*/
public int specificIndex = -1;
-
+
/**
* This filter has specified the Intent.CATEGORY_DEFAULT, meaning it
* would like to be considered a default action that the user can
* perform on this data.
*/
public boolean isDefault;
-
+
/**
* A string resource identifier (in the package's resources) of this
* match's label. From the "label" attribute or, if not set, 0.
*/
public int labelRes;
-
+
/**
* The actual string retrieve from <var>labelRes</var> or null if none
* was provided.
*/
public CharSequence nonLocalizedLabel;
-
+
/**
* A drawable resource identifier (in the package's resources) of this
- * match's icon. From the "icon" attribute or, if not set, 0.
+ * match's icon. From the "icon" attribute or, if not set, 0. It is
+ * set only if the icon can be obtained by resource id alone.
*/
public int icon;
@@ -134,11 +135,21 @@
public int targetUserId;
/**
+ * Set to true if the icon cannot be obtained by resource ids alone.
+ * It is set to true for ResolveInfos from the managed profile: They need to
+ * have their icon badged, so it cannot be obtained by resource ids alone.
* @hide
*/
public boolean noResourceId;
/**
+ * Same as {@link #icon} but it will always correspond to "icon" attribute
+ * regardless of {@link #noResourceId} value.
+ * @hide
+ */
+ public int iconResourceId;
+
+ /**
* @hide Target comes from system process?
*/
public boolean system;
@@ -159,10 +170,10 @@
* Retrieve the current textual label associated with this resolution. This
* will call back on the given PackageManager to load the label from
* the application.
- *
+ *
* @param pm A PackageManager from which the label can be loaded; usually
* the PackageManager from which you originally retrieved this item.
- *
+ *
* @return Returns a CharSequence containing the resolutions's label. If the
* item does not have a label, its name is returned.
*/
@@ -191,33 +202,30 @@
if (data != null) data = data.toString().trim();
return data;
}
-
+
/**
* Retrieve the current graphical icon associated with this resolution. This
* will call back on the given PackageManager to load the icon from
* the application.
- *
+ *
* @param pm A PackageManager from which the icon can be loaded; usually
* the PackageManager from which you originally retrieved this item.
- *
+ *
* @return Returns a Drawable containing the resolution's icon. If the
* item does not have an icon, the default activity icon is returned.
*/
public Drawable loadIcon(PackageManager pm) {
- Drawable dr;
- if (resolvePackageName != null && icon != 0) {
- dr = pm.getDrawable(resolvePackageName, icon, null);
- if (dr != null) {
- return dr;
- }
+ Drawable dr = null;
+ if (resolvePackageName != null && iconResourceId != 0) {
+ dr = pm.getDrawable(resolvePackageName, iconResourceId, null);
}
ComponentInfo ci = getComponentInfo();
- ApplicationInfo ai = ci.applicationInfo;
- if (icon != 0) {
- dr = pm.getDrawable(ci.packageName, icon, ai);
- if (dr != null) {
- return dr;
- }
+ if (dr == null && iconResourceId != 0) {
+ ApplicationInfo ai = ci.applicationInfo;
+ dr = pm.getDrawable(ci.packageName, iconResourceId, ai);
+ }
+ if (dr != null) {
+ return pm.getUserBadgedIcon(dr, new UserHandle(UserHandle.myUserId()));
}
return ci.loadIcon(pm);
}
@@ -231,7 +239,7 @@
* @return The icon associated with this match.
*/
final int getIconResourceInternal() {
- if (icon != 0) return icon;
+ if (iconResourceId != 0) return iconResourceId;
final ComponentInfo ci = getComponentInfo();
if (ci != null) {
return ci.getIconResource();
@@ -298,6 +306,8 @@
nonLocalizedLabel = orig.nonLocalizedLabel;
icon = orig.icon;
resolvePackageName = orig.resolvePackageName;
+ noResourceId = orig.noResourceId;
+ iconResourceId = orig.iconResourceId;
system = orig.system;
targetUserId = orig.targetUserId;
handleAllWebDataURI = orig.handleAllWebDataURI;
@@ -362,6 +372,7 @@
dest.writeInt(targetUserId);
dest.writeInt(system ? 1 : 0);
dest.writeInt(noResourceId ? 1 : 0);
+ dest.writeInt(iconResourceId);
dest.writeInt(handleAllWebDataURI ? 1 : 0);
}
@@ -408,9 +419,10 @@
targetUserId = source.readInt();
system = source.readInt() != 0;
noResourceId = source.readInt() != 0;
+ iconResourceId = source.readInt();
handleAllWebDataURI = source.readInt() != 0;
}
-
+
public static class DisplayNameComparator
implements Comparator<ResolveInfo> {
public DisplayNameComparator(PackageManager pm) {
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index f8db6d9..c656fb8b 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -667,7 +667,7 @@
* {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.
* The fps range can be controlled via {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}.</p>
* <p>In this capability, the camera device will override aeMode, awbMode, and afMode to
- * ON, ON, and CONTINUOUS_VIDEO, respectively. All post-processing block mode
+ * ON, AUTO, and CONTINUOUS_VIDEO, respectively. All post-processing block mode
* controls will be overridden to be FAST. Therefore, no manual control of capture
* and post-processing parameters is possible. All other controls operate the
* same as when {@link CaptureRequest#CONTROL_MODE android.control.mode} == AUTO. This means that all other
@@ -1666,9 +1666,9 @@
* <p>Enabling this disables control.aeMode, control.awbMode and
* control.afMode controls; the camera device will ignore
* those settings while USE_SCENE_MODE is active (except for
- * FACE_PRIORITY scene mode). Other control entries are still
- * active. This setting can only be used if scene mode is
- * supported (i.e. {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}
+ * FACE_PRIORITY scene mode). Other control entries are still active.
+ * This setting can only be used if scene mode is supported (i.e.
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}
* contain some modes other than DISABLED).</p>
*
* @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
@@ -1940,6 +1940,40 @@
*/
public static final int CONTROL_SCENE_MODE_HDR = 18;
+ /**
+ * <p>Same as FACE_PRIORITY scene mode, except that the camera
+ * device will choose higher sensivity values ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
+ * under low light conditions.</p>
+ * <p>The camera device may be tuned to expose the images in a reduced
+ * sensitivity range to produce the best quality images. For example,
+ * if the {@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange} gives range of [100, 1600],
+ * the camera device auto-exposure routine tuning process may limit the actual
+ * exposure sensivity range to [100, 1200] to ensure that the noise level isn't
+ * exessive to compromise the image quality. Under this situation, the image under
+ * low light may be under-exposed when the sensor max exposure time (bounded by the
+ * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange} when {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is one of the
+ * ON_* modes) and effecitve max sensitivity are reached. This scene mode allows the
+ * camera device auto-exposure routine to increase the sensitivity up to the max
+ * sensitivity specified by {@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange} when the scene is too
+ * dark and the max exposure time is reached. The captured images may be noisier
+ * compared with the images captured in normal FACE_PRIORITY mode, therefore, it is
+ * recommended that the application only use this scene mode when it is capable of
+ * reducing the noise level of the captured images.</p>
+ * <p>Unlike the other scene modes, {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
+ * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}
+ * remain active when FACE_PRIORITY_LOW_LIGHT is set.</p>
+ *
+ * @see CaptureRequest#CONTROL_AE_MODE
+ * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+ * @see CaptureRequest#CONTROL_AF_MODE
+ * @see CaptureRequest#CONTROL_AWB_MODE
+ * @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
+ * @see CaptureRequest#SENSOR_SENSITIVITY
+ * @see CaptureRequest#CONTROL_SCENE_MODE
+ * @hide
+ */
+ public static final int CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT = 19;
+
//
// Enumeration values for CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
//
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index bc625dd..9fa6687 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1448,9 +1448,9 @@
* <p>Scene modes are custom camera modes optimized for a certain set of conditions and
* capture settings.</p>
* <p>This is the mode that that is active when
- * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
- * these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
- * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+ * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY, these modes will
+ * disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}, {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}
+ * while in use.</p>
* <p>The interpretation and implementation of these scene modes is left
* to the implementor of the camera device. Their behavior will not be
* consistent across all devices, and any given device may only implement
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index da216aa..b1fb615 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1960,9 +1960,9 @@
* <p>Scene modes are custom camera modes optimized for a certain set of conditions and
* capture settings.</p>
* <p>This is the mode that that is active when
- * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
- * these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
- * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+ * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY, these modes will
+ * disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}, {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}
+ * while in use.</p>
* <p>The interpretation and implementation of these scene modes is left
* to the implementor of the camera device. Their behavior will not be
* consistent across all devices, and any given device may only implement
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d165240..eb6e1c2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1165,25 +1165,23 @@
public static final int EVENT_USER_FOREGROUND = 0x0008;
// Event for connectivity changed.
public static final int EVENT_CONNECTIVITY_CHANGED = 0x0009;
- // Event for significant motion taking us out of idle mode.
- public static final int EVENT_SIGNIFICANT_MOTION = 0x000a;
// Event for becoming active taking us out of idle mode.
- public static final int EVENT_ACTIVE = 0x000b;
+ public static final int EVENT_ACTIVE = 0x000a;
// Event for a package being installed.
- public static final int EVENT_PACKAGE_INSTALLED = 0x000c;
+ public static final int EVENT_PACKAGE_INSTALLED = 0x000b;
// Event for a package being uninstalled.
- public static final int EVENT_PACKAGE_UNINSTALLED = 0x000d;
+ public static final int EVENT_PACKAGE_UNINSTALLED = 0x000c;
// Event for a package being uninstalled.
- public static final int EVENT_ALARM = 0x000e;
+ public static final int EVENT_ALARM = 0x000d;
// Record that we have decided we need to collect new stats data.
- public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f;
+ public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000e;
// Event for a package becoming inactive due to being unused for a period of time.
- public static final int EVENT_PACKAGE_INACTIVE = 0x0010;
+ public static final int EVENT_PACKAGE_INACTIVE = 0x000f;
// Event for a package becoming active due to an interaction.
- public static final int EVENT_PACKAGE_ACTIVE = 0x0011;
+ public static final int EVENT_PACKAGE_ACTIVE = 0x0010;
// Number of event types.
- public static final int EVENT_COUNT = 0x0012;
+ public static final int EVENT_COUNT = 0x0011;
// Mask to extract out only the type part of the event.
public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
@@ -1840,12 +1838,12 @@
public static final String[] HISTORY_EVENT_NAMES = new String[] {
"null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
- "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
+ "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
};
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
"Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
- "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
+ "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
};
/**
@@ -4017,8 +4015,10 @@
if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
sb.setLength(0);
sb.append(prefix);
- sb.append(" Total cpu time: ");
- formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000);
+ sb.append(" Total cpu time: u=");
+ formatTimeMs(sb, userCpuTimeUs / 1000);
+ sb.append("s=");
+ formatTimeMs(sb, systemCpuTimeUs / 1000);
pw.println(sb.toString());
}
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 268295d..fe4aa13 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -28,4 +28,5 @@
int[] getAppIdTempWhitelist();
boolean isPowerSaveWhitelistApp(String name);
void addPowerSaveTempWhitelistApp(String name, long duration, int userId);
+ void exitIdle(String reason);
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index dbb5146..f9c50f3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -635,8 +635,8 @@
if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) {
argsForZygote.add("--enable-jit");
}
- if ((debugFlags & Zygote.DEBUG_GENERATE_CFI) != 0) {
- argsForZygote.add("--generate-cfi");
+ if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
+ argsForZygote.add("--generate-debug-info");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 3fb93c4..62c28ac 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -81,8 +81,8 @@
public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000;
public static final int KM_TAG_NONCE = KM_BYTES | 1001;
- public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1003;
- public static final int KM_TAG_MAC_LENGTH = KM_INT | 1004;
+ public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1002;
+ public static final int KM_TAG_MAC_LENGTH = KM_INT | 1003;
// Algorithm values.
public static final int KM_ALGORITHM_RSA = 1;
@@ -191,8 +191,9 @@
public static final int KM_ERROR_MISSING_NONCE = -51;
public static final int KM_ERROR_INVALID_NONCE = -52;
public static final int KM_ERROR_MISSING_MAC_LENGTH = -53;
- public static final int KM_ERROR_RESCOPABLE_KEY_NOT_USABLE = -54;
+ public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54;
public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
+ public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56;
public static final int KM_ERROR_UNIMPLEMENTED = -100;
public static final int KM_ERROR_VERSION_MISMATCH = -101;
public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 8c6cd09..0309d24 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -41,6 +41,7 @@
import android.util.ArraySet;
import android.util.Log;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -463,15 +464,28 @@
ParceledListSlice<StatusBarNotification> parceledList = getNotificationInterface()
.getActiveNotificationsFromListener(mWrapper, keys, trim);
List<StatusBarNotification> list = parceledList.getList();
-
+ ArrayList<StatusBarNotification> corruptNotifications = null;
int N = list.size();
for (int i = 0; i < N; i++) {
- Notification notification = list.get(i).getNotification();
- Builder.rebuild(getContext(), notification);
- // convert icon metadata to legacy format for older clients
- createLegacyIconExtras(notification);
+ StatusBarNotification sbn = list.get(i);
+ Notification notification = sbn.getNotification();
+ try {
+ Builder.rebuild(getContext(), notification);
+ // convert icon metadata to legacy format for older clients
+ createLegacyIconExtras(notification);
+ } catch (IllegalArgumentException e) {
+ if (corruptNotifications == null) {
+ corruptNotifications = new ArrayList<>(N);
+ }
+ corruptNotifications.add(sbn);
+ Log.w(TAG, "onNotificationPosted: can't rebuild notification from " +
+ sbn.getPackageName());
+ }
}
- return list.toArray(new StatusBarNotification[N]);
+ if (corruptNotifications != null) {
+ list.removeAll(corruptNotifications);
+ }
+ return list.toArray(new StatusBarNotification[list.size()]);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -671,16 +685,28 @@
Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);
return;
}
- Notification.Builder.rebuild(getContext(), sbn.getNotification());
- // convert icon metadata to legacy format for older clients
- createLegacyIconExtras(sbn.getNotification());
+ try {
+ Notification.Builder.rebuild(getContext(), sbn.getNotification());
+ // convert icon metadata to legacy format for older clients
+ createLegacyIconExtras(sbn.getNotification());
+ } catch (IllegalArgumentException e) {
+ // drop corrupt notification
+ sbn = null;
+ Log.w(TAG, "onNotificationPosted: can't rebuild notification from " +
+ sbn.getPackageName());
+ }
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
synchronized (mWrapper) {
applyUpdate(update);
try {
- NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
+ if (sbn != null) {
+ NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
+ } else {
+ // still pass along the ranking map, it may contain other information
+ NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
+ }
} catch (Throwable t) {
Log.w(TAG, "Error running onNotificationPosted", t);
}
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index 80dcecc..ea979c8 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -261,6 +261,16 @@
public abstract MenuInflater getMenuInflater();
/**
+ * Called when the window containing the view that started this action mode gains or loses
+ * focus.
+ *
+ * @param hasWindowFocus True if the window containing the view that started this action mode
+ * now has focus, false otherwise.
+ *
+ */
+ public void onWindowFocusChanged(boolean hasWindowFocus) {}
+
+ /**
* Returns whether the UI presenting this action mode can take focus or not.
* This is used by internal components within the framework that would otherwise
* present an action mode UI that requires focus, such as an EditText as a custom view.
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 2f5c9e2..7db88af 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -298,14 +298,27 @@
* Notify the host application to handle a SSL client certificate
* request. The host application is responsible for showing the UI
* if desired and providing the keys. There are three ways to
- * respond: proceed(), cancel() or ignore(). Webview remembers the
- * response if proceed() or cancel() is called and does not
- * call onReceivedClientCertRequest() again for the same host and port
- * pair. Webview does not remember the response if ignore() is called.
+ * respond: proceed(), cancel() or ignore(). Webview stores the response
+ * in memory (for the life of the application) if proceed() or cancel() is
+ * called and does not call onReceivedClientCertRequest() again for the
+ * same host and port pair. Webview does not store the response if ignore()
+ * is called.
*
* This method is called on the UI thread. During the callback, the
* connection is suspended.
*
+ * For most use cases, the application program should implement the
+ * {@link android.security.KeyChainAliasCallback} interface and pass it to
+ * {@link android.security.KeyChain.choosePrivateKeyAlias} to start an
+ * activity for the user to choose the proper alias. The keychain activity will
+ * provide the alias through the callback method in the implemented interface. Next
+ * the application should create an async task to call
+ * {@link android.security.KeyChain.getPrivateKey} to receive the key.
+ *
+ * An example implementation of client certificates can be seen at
+ * <A href="https://android.googlesource.com/platform/packages/apps/Browser/+/android-5.1.1_r1/src/com/android/browser/Tab.java">
+ * AOSP Browser</a>
+ *
* The default behavior is to cancel, returning no client certificate.
*
* @param view The WebView that is initiating the callback
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index b4ef58a..3b9aca8 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -96,49 +96,27 @@
public MissingWebViewPackageException(Exception e) { super(e); }
}
- /** @hide */
- public static String[] getWebViewPackageNames() {
- return AppGlobals.getInitialApplication().getResources().getStringArray(
- com.android.internal.R.array.config_webViewPackageNames);
- }
-
- // TODO (gsennton) remove when committing webview xts test change
public static String getWebViewPackageName() {
- String[] webViewPackageNames = getWebViewPackageNames();
- return webViewPackageNames[webViewPackageNames.length-1];
+ return AppGlobals.getInitialApplication().getString(
+ com.android.internal.R.string.config_webViewPackageName);
}
- /**
- * Return the package info of the first package in the webview priority list that contains
- * webview.
- *
- * @hide
- */
- public static PackageInfo findPreferredWebViewPackage() {
+ private static PackageInfo fetchPackageInfo() {
PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
-
- for (String packageName : getWebViewPackageNames()) {
- try {
- PackageInfo packageInfo = pm.getPackageInfo(packageName,
- PackageManager.GET_META_DATA);
- ApplicationInfo applicationInfo = packageInfo.applicationInfo;
-
- // If the correct flag is set the package contains webview.
- if (getWebViewLibrary(applicationInfo) != null) {
- return packageInfo;
- }
- } catch (PackageManager.NameNotFoundException e) {
- }
+ try {
+ return pm.getPackageInfo(getWebViewPackageName(), PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new MissingWebViewPackageException(e);
}
- throw new MissingWebViewPackageException("Could not find a loadable WebView package");
}
// throws MissingWebViewPackageException
private static ApplicationInfo getWebViewApplicationInfo() {
- if (sPackageInfo == null)
- return findPreferredWebViewPackage().applicationInfo;
- else
+ if (sPackageInfo == null) {
+ return fetchPackageInfo().applicationInfo;
+ } else {
return sPackageInfo.applicationInfo;
+ }
}
private static String getWebViewLibrary(ApplicationInfo ai) {
@@ -153,10 +131,10 @@
/**
* Load the native library for the given package name iff that package
- * name is the same as the one providing the current webview.
+ * name is the same as the one providing the webview.
*/
public static int loadWebViewNativeLibraryFromPackage(String packageName) {
- sPackageInfo = findPreferredWebViewPackage();
+ sPackageInfo = fetchPackageInfo();
if (packageName != null && packageName.equals(sPackageInfo.packageName)) {
return loadNativeLibrary();
}
@@ -202,7 +180,7 @@
private static Class<WebViewFactoryProvider> getProviderClass() {
try {
// First fetch the package info so we can log the webview package version.
- sPackageInfo = findPreferredWebViewPackage();
+ sPackageInfo = fetchPackageInfo();
Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
@@ -241,8 +219,8 @@
try {
// Construct a package context to load the Java code into the current app.
Context webViewContext = initialApplication.createPackageContext(
- sPackageInfo.packageName,
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ sPackageInfo.packageName,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
initialApplication.getAssets().addAssetPath(
webViewContext.getApplicationInfo().sourceDir);
ClassLoader clazzLoader = webViewContext.getClassLoader();
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index a15080e..ebb54ff 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -17,6 +17,7 @@
package android.widget;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
@@ -24,6 +25,7 @@
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.RemoteViews.RemoteView;
import java.util.Formatter;
@@ -58,6 +60,7 @@
}
private long mBase;
+ private long mNow; // the currently displayed time
private boolean mVisible;
private boolean mStarted;
private boolean mRunning;
@@ -224,6 +227,7 @@
}
private synchronized void updateText(long now) {
+ mNow = now;
long seconds = now - mBase;
seconds /= 1000;
String text = DateUtils.formatElapsedTime(mRecycle, seconds);
@@ -279,6 +283,60 @@
}
}
+ private static final int MIN_IN_SEC = 60;
+ private static final int HOUR_IN_SEC = MIN_IN_SEC*60;
+ private static String formatDuration(long ms) {
+ final Resources res = Resources.getSystem();
+ final StringBuilder text = new StringBuilder();
+
+ int duration = (int) (ms / DateUtils.SECOND_IN_MILLIS);
+ if (duration < 0) {
+ duration = -duration;
+ }
+
+ int h = 0;
+ int m = 0;
+
+ if (duration >= HOUR_IN_SEC) {
+ h = duration / HOUR_IN_SEC;
+ duration -= h * HOUR_IN_SEC;
+ }
+ if (duration >= MIN_IN_SEC) {
+ m = duration / MIN_IN_SEC;
+ duration -= m * MIN_IN_SEC;
+ }
+ int s = duration;
+
+ try {
+ if (h > 0) {
+ text.append(res.getQuantityString(
+ com.android.internal.R.plurals.duration_hours, h, h));
+ }
+ if (m > 0) {
+ if (text.length() > 0) {
+ text.append(' ');
+ }
+ text.append(res.getQuantityString(
+ com.android.internal.R.plurals.duration_minutes, m, m));
+ }
+
+ if (text.length() > 0) {
+ text.append(' ');
+ }
+ text.append(res.getQuantityString(
+ com.android.internal.R.plurals.duration_seconds, s, s));
+ } catch (Resources.NotFoundException e) {
+ // Ignore; plurals throws an exception for an untranslated quantity for a given locale.
+ return null;
+ }
+ return text.toString();
+ }
+
+ @Override
+ public CharSequence getContentDescription() {
+ return formatDuration(mNow - mBase);
+ }
+
@Override
public CharSequence getAccessibilityClassName() {
return Chronometer.class.getName();
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 339038e..affc5da 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -522,7 +522,7 @@
View baselineView = null;
LayoutParams baselineParams = null;
for (int i = 0; i < count; i++) {
- final View child = views[i];
+ final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final LayoutParams childParams = (LayoutParams) child.getLayoutParams();
if (baselineView == null || baselineParams == null
@@ -548,9 +548,9 @@
if (offsetHorizontalAxis) {
for (int i = 0; i < count; i++) {
- final View child = views[i];
+ View child = getChildAt(i);
if (child.getVisibility() != GONE) {
- final LayoutParams params = (LayoutParams) child.getLayoutParams();
+ LayoutParams params = (LayoutParams) child.getLayoutParams();
final int[] rules = params.getRules(layoutDirection);
if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
centerHorizontal(child, params, width);
@@ -578,9 +578,9 @@
if (offsetVerticalAxis) {
for (int i = 0; i < count; i++) {
- final View child = views[i];
+ View child = getChildAt(i);
if (child.getVisibility() != GONE) {
- final LayoutParams params = (LayoutParams) child.getLayoutParams();
+ LayoutParams params = (LayoutParams) child.getLayoutParams();
final int[] rules = params.getRules(layoutDirection);
if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
centerVertical(child, params, height);
@@ -607,9 +607,9 @@
final int verticalOffset = contentBounds.top - top;
if (horizontalOffset != 0 || verticalOffset != 0) {
for (int i = 0; i < count; i++) {
- final View child = views[i];
+ View child = getChildAt(i);
if (child.getVisibility() != GONE && child != ignore) {
- final LayoutParams params = (LayoutParams) child.getLayoutParams();
+ LayoutParams params = (LayoutParams) child.getLayoutParams();
if (horizontalGravity) {
params.mLeft += horizontalOffset;
params.mRight += horizontalOffset;
@@ -626,9 +626,9 @@
if (isLayoutRtl()) {
final int offsetWidth = myWidth - width;
for (int i = 0; i < count; i++) {
- final View child = views[i];
+ View child = getChildAt(i);
if (child.getVisibility() != GONE) {
- final LayoutParams params = (LayoutParams) child.getLayoutParams();
+ LayoutParams params = (LayoutParams) child.getLayoutParams();
params.mLeft -= offsetWidth;
params.mRight -= offsetWidth;
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c1ec6e6..2a13c76 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -613,15 +613,17 @@
ri.activityInfo = ai;
UserManager userManager =
(UserManager) getSystemService(Context.USER_SERVICE);
- if (userManager.isManagedProfile()) {
- ri.noResourceId = true;
- }
if (ii instanceof LabeledIntent) {
LabeledIntent li = (LabeledIntent)ii;
ri.resolvePackageName = li.getSourcePackage();
ri.labelRes = li.getLabelResource();
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
+ ri.iconResourceId = ri.icon;
+ }
+ if (userManager.isManagedProfile()) {
+ ri.noResourceId = true;
+ ri.icon = 0;
}
mCallerTargets.add(new DisplayResolveInfo(ii, ri,
ri.loadLabel(pm), null, ii));
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 929cacd..6f0cec6 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -116,7 +116,7 @@
void noteWifiRadioPowerState(int powerState, long timestampNs);
void noteNetworkInterfaceType(String iface, int type);
void noteNetworkStatsEnabled();
- void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion);
+ void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid);
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 39c86f9..e14f058 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1186,15 +1186,17 @@
ri.activityInfo = ai;
UserManager userManager =
(UserManager) getSystemService(Context.USER_SERVICE);
- if (userManager.isManagedProfile()) {
- ri.noResourceId = true;
- }
if (ii instanceof LabeledIntent) {
LabeledIntent li = (LabeledIntent)ii;
ri.resolvePackageName = li.getSourcePackage();
ri.labelRes = li.getLabelResource();
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
+ ri.iconResourceId = ri.icon;
+ }
+ if (userManager.isManagedProfile()) {
+ ri.noResourceId = true;
+ ri.icon = 0;
}
addResolveInfo(new DisplayResolveInfo(ii, ri,
ri.loadLabel(getPackageManager()), null, ii));
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 07d1fc8..229079f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -95,7 +95,8 @@
public final class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
- private static final boolean DEBUG_ENERGY = false;
+ public static final boolean DEBUG_ENERGY = false;
+ private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false;
private static final boolean DEBUG_HISTORY = false;
private static final boolean USE_OLD_HISTORY = false; // for debugging.
@@ -105,7 +106,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 127 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 128 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -151,6 +152,9 @@
BatteryCallback cb = mCallback;
switch (msg.what) {
case MSG_UPDATE_WAKELOCKS:
+ synchronized (BatteryStatsImpl.this) {
+ updateCpuTimeLocked();
+ }
if (cb != null) {
cb.batteryNeedsCpuUpdate();
}
@@ -178,6 +182,7 @@
public interface ExternalStatsSync {
void scheduleSync(String reason);
+ void scheduleWifiSync(String reason);
}
public final MyHandler mHandler;
@@ -2503,12 +2508,11 @@
boolean unpluggedScreenOff = unplugged && screenOff;
if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
updateKernelWakelocksLocked();
- requestWakelockCpuUpdate();
- if (!unpluggedScreenOff) {
- // We are switching to no longer tracking wake locks, but we want
- // the next CPU update we receive to take them in to account.
- mDistributeWakelockCpu = true;
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Updating cpu time because screen is now " +
+ (unpluggedScreenOff ? "off" : "on"));
}
+ updateCpuTimeLocked();
mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
}
}
@@ -2772,10 +2776,14 @@
mWakeLockNesting++;
}
if (uid >= 0) {
- //if (uid == 0) {
- // Slog.wtf(TAG, "Acquiring wake lock from root: " + name);
- //}
- requestWakelockCpuUpdate();
+ if (mOnBatteryScreenOffTimeBase.isRunning()) {
+ // We only update the cpu time when a wake lock is acquired if the screen is off.
+ // If the screen is on, we don't distribute the power amongst partial wakelocks.
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Updating cpu time because of +wake_lock");
+ }
+ requestWakelockCpuUpdate();
+ }
getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
}
}
@@ -2805,7 +2813,12 @@
}
}
if (uid >= 0) {
- requestWakelockCpuUpdate();
+ if (mOnBatteryScreenOffTimeBase.isRunning()) {
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Updating cpu time because of -wake_lock");
+ }
+ requestWakelockCpuUpdate();
+ }
getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
}
}
@@ -2874,46 +2887,14 @@
addHistoryRecordLocked(elapsedRealtime, uptime);
}
- public int startAddingCpuLocked() {
+ public boolean startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
-
- if (!mOnBatteryInternal) {
- return -1;
- }
-
- final int N = mPartialTimers.size();
- if (N == 0) {
- mLastPartialTimers.clear();
- mDistributeWakelockCpu = false;
- return 0;
- }
-
- if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) {
- return 0;
- }
-
- mDistributeWakelockCpu = false;
-
- // How many timers should consume CPU? Only want to include ones
- // that have already been in the list.
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- if (st.mInList) {
- Uid uid = st.mUid;
- // We don't include the system UID, because it so often
- // holds wake locks at one request or another of an app.
- if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- return 50;
- }
- }
- }
-
- return 0;
+ return mOnBatteryInternal;
}
- public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime,
- int totalUTime, int totalSTime, int statUserTime, int statSystemTime,
- int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime) {
+ public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
+ int statSystemTime, int statIOWaitTime, int statIrqTime,
+ int statSoftIrqTime, int statIdleTime) {
if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
+ " user=" + statUserTime + " sys=" + statSystemTime
+ " io=" + statIOWaitTime + " irq=" + statIrqTime
@@ -2926,70 +2907,6 @@
mCurStepStatIrqTime += statIrqTime;
mCurStepStatSoftIrqTime += statSoftIrqTime;
mCurStepStatIdleTime += statIdleTime;
-
- final int N = mPartialTimers.size();
- if (perc != 0) {
- int num = 0;
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- if (st.mInList) {
- Uid uid = st.mUid;
- // We don't include the system UID, because it so often
- // holds wake locks at one request or another of an app.
- if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- num++;
- }
- }
- }
- if (num != 0) {
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- if (st.mInList) {
- Uid uid = st.mUid;
- if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- int myUTime = remainUTime/num;
- int mySTime = remainSTtime/num;
- remainUTime -= myUTime;
- remainSTtime -= mySTime;
- num--;
- Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
- proc.addCpuTimeLocked(myUTime, mySTime);
- }
- }
- }
- }
-
- // Just in case, collect any lost CPU time.
- if (remainUTime != 0 || remainSTtime != 0) {
- Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
- if (uid != null) {
- Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
- proc.addCpuTimeLocked(remainUTime, remainSTtime);
- }
- }
- }
-
- final int NL = mLastPartialTimers.size();
- boolean diff = N != NL;
- for (int i=0; i<NL && !diff; i++) {
- diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
- }
- if (!diff) {
- for (int i=0; i<NL; i++) {
- mPartialTimers.get(i).mInList = true;
- }
- return;
- }
-
- for (int i=0; i<NL; i++) {
- mLastPartialTimers.get(i).mInList = false;
- }
- mLastPartialTimers.clear();
- for (int i=0; i<N; i++) {
- StopwatchTimer st = mPartialTimers.get(i);
- st.mInList = true;
- mLastPartialTimers.add(st);
- }
}
public void noteProcessDiedLocked(int uid, int pid) {
@@ -3271,11 +3188,11 @@
}
}
- public void noteDeviceIdleModeLocked(boolean enabled, boolean fromActive, boolean fromMotion) {
+ public void noteDeviceIdleModeLocked(boolean enabled, String activeReason, int activeUid) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
boolean nowIdling = enabled;
- if (mDeviceIdling && !enabled && !fromActive && !fromMotion) {
+ if (mDeviceIdling && !enabled && activeReason == null) {
// We don't go out of general idling mode until explicitly taken out of
// device idle through going active or significant motion.
nowIdling = true;
@@ -3293,14 +3210,8 @@
}
if (mDeviceIdleModeEnabled != enabled) {
mDeviceIdleModeEnabled = enabled;
- if (fromMotion) {
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SIGNIFICANT_MOTION,
- "", 0);
- }
- if (fromActive) {
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
- "", 0);
- }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
+ activeReason != null ? activeReason : "", activeUid);
if (enabled) {
mHistoryCur.states2 |= HistoryItem.STATE2_DEVICE_IDLE_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode enabled to: "
@@ -3580,7 +3491,7 @@
addHistoryRecordLocked(elapsedRealtime, uptime);
mWifiOn = true;
mWifiOnTimer.startRunningLocked(elapsedRealtime);
- scheduleSyncExternalStatsLocked("wifi-off");
+ scheduleSyncExternalWifiStatsLocked("wifi-off");
}
}
@@ -3594,7 +3505,7 @@
addHistoryRecordLocked(elapsedRealtime, uptime);
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(elapsedRealtime);
- scheduleSyncExternalStatsLocked("wifi-on");
+ scheduleSyncExternalWifiStatsLocked("wifi-on");
}
}
@@ -3846,7 +3757,7 @@
int uid = mapUid(ws.get(i));
getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
}
- scheduleSyncExternalStatsLocked("wifi-running");
+ scheduleSyncExternalWifiStatsLocked("wifi-running");
} else {
Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
}
@@ -3885,7 +3796,7 @@
int uid = mapUid(ws.get(i));
getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
}
- scheduleSyncExternalStatsLocked("wifi-stopped");
+ scheduleSyncExternalWifiStatsLocked("wifi-stopped");
} else {
Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
}
@@ -3900,7 +3811,7 @@
}
mWifiState = wifiState;
mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
- scheduleSyncExternalStatsLocked("wifi-state");
+ scheduleSyncExternalWifiStatsLocked("wifi-state");
}
}
@@ -7632,6 +7543,10 @@
* @param info The energy information from the WiFi controller.
*/
public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
+ if (DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating wifi stats");
+ }
+
final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
NetworkStats delta = null;
try {
@@ -7829,6 +7744,10 @@
* Distribute Cell radio energy info and network traffic to apps.
*/
public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
+ if (DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating mobile radio stats");
+ }
+
NetworkStats delta = null;
try {
if (!ArrayUtils.isEmpty(mMobileIfaces)) {
@@ -7901,6 +7820,10 @@
* @param info The energy information from the bluetooth controller.
*/
public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
+ if (DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating bluetooth stats");
+ }
+
if (info != null && mOnBatteryInternal) {
mHasBluetoothEnergyReporting = true;
mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
@@ -7959,30 +7882,196 @@
}
}
+ // We use an anonymous class to access these variables,
+ // so they can't live on the stack or they'd have to be
+ // final MutableLong objects (more allocations).
+ // Used in updateCpuTimeLocked().
+ long mTempTotalCpuUserTimeUs;
+ long mTempTotalCpuSystemTimeUs;
+
/**
- * Read and distribute CPU usage across apps.
+ * Read and distribute CPU usage across apps. If their are partial wakelocks being held
+ * and we are on battery with screen off, we give more of the cpu time to those apps holding
+ * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
*/
- public void updateCpuTimeLocked(boolean firstTime) {
+ public void updateCpuTimeLocked() {
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "!Cpu updating!");
+ }
+
+ // Holding a wakelock costs more than just using the cpu.
+ // Currently, we assign only half the cpu time to an app that is running but
+ // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
+ // If no app is holding a wakelock, then the distribution is normal.
+ final int wakelockWeight = 50;
+
+ // Read the time spent at various cpu frequencies.
final int cpuSpeedSteps = getCpuSpeedSteps();
final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta();
- KernelUidCpuTimeReader.Callback callback = null;
- if (mOnBatteryInternal && !firstTime) {
- callback = new KernelUidCpuTimeReader.Callback() {
- @Override
- public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
- final Uid u = getUidStatsLocked(mapUid(uid));
- u.mUserCpuTime.addCountLocked(userTimeUs);
- u.mSystemCpuTime.addCountLocked(systemTimeUs);
- for (int i = 0; i < cpuSpeedSteps; i++) {
- if (u.mSpeedBins[i] == null) {
- u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
- }
- u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
- }
+
+ int numWakelocks = 0;
+
+ // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
+ // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
+ final int numPartialTimers = mPartialTimers.size();
+ if (mOnBatteryScreenOffTimeBase.isRunning()) {
+ for (int i = 0; i < numPartialTimers; i++) {
+ final StopwatchTimer timer = mPartialTimers.get(i);
+ if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
+ // Since the collection and blaming of wakelocks can be scheduled to run after
+ // some delay, the mPartialTimers list may have new entries. We can't blame
+ // the newly added timer for past cpu time, so we only consider timers that
+ // were present for one round of collection. Once a timer has gone through
+ // a round of collection, its mInList field is set to true.
+ numWakelocks++;
}
- };
+ }
}
- mKernelUidCpuTimeReader.readDelta(callback);
+
+ final int numWakelocksF = numWakelocks;
+ mTempTotalCpuUserTimeUs = 0;
+ mTempTotalCpuSystemTimeUs = 0;
+
+ // Read the CPU data for each UID. This will internally generate a snapshot so next time
+ // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
+ // we just ignore the data.
+ final long startTimeMs = SystemClock.elapsedRealtime();
+ mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
+ new KernelUidCpuTimeReader.Callback() {
+ @Override
+ public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
+ final Uid u = getUidStatsLocked(mapUid(uid));
+
+ // Accumulate the total system and user time.
+ mTempTotalCpuUserTimeUs += userTimeUs;
+ mTempTotalCpuSystemTimeUs += systemTimeUs;
+
+ StringBuilder sb = null;
+ if (DEBUG_ENERGY_CPU) {
+ sb = new StringBuilder();
+ sb.append(" got time for uid=").append(u.mUid).append(": u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ sb.append("\n");
+ }
+
+ if (numWakelocksF > 0) {
+ // We have wakelocks being held, so only give a portion of the
+ // time to the process. The rest will be distributed among wakelock
+ // holders.
+ userTimeUs = (userTimeUs * wakelockWeight) / 100;
+ systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
+ }
+
+ if (sb != null) {
+ sb.append(" adding to uid=").append(u.mUid).append(": u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ Slog.d(TAG, sb.toString());
+ }
+
+ u.mUserCpuTime.addCountLocked(userTimeUs);
+ u.mSystemCpuTime.addCountLocked(systemTimeUs);
+
+ // Add the cpu speeds to this UID. These are used as a ratio
+ // for computing the power this UID used.
+ for (int i = 0; i < cpuSpeedSteps; i++) {
+ if (u.mSpeedBins[i] == null) {
+ u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+ }
+ u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
+ }
+ }
+ });
+
+ if (DEBUG_ENERGY_CPU) {
+ Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) +
+ " ms");
+ }
+
+ if (mOnBatteryInternal && numWakelocks > 0) {
+ // Distribute a portion of the total cpu time to wakelock holders.
+ mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
+ mTempTotalCpuSystemTimeUs =
+ (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
+
+ for (int i = 0; i < numPartialTimers; i++) {
+ final StopwatchTimer timer = mPartialTimers.get(i);
+
+ // The system does not share any blame, as it is usually holding the wakelock
+ // on behalf of an app.
+ if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
+ int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
+ int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
+
+ if (DEBUG_ENERGY_CPU) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" Distributing wakelock uid=").append(timer.mUid.mUid)
+ .append(": u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ Slog.d(TAG, sb.toString());
+ }
+
+ timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
+ timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
+
+ final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
+ proc.addCpuTimeLocked(userTimeUs, systemTimeUs);
+
+ mTempTotalCpuUserTimeUs -= userTimeUs;
+ mTempTotalCpuSystemTimeUs -= systemTimeUs;
+ numWakelocks--;
+ }
+ }
+
+ if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
+ // Anything left over is given to the system.
+ if (DEBUG_ENERGY_CPU) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" Distributing lost time to system: u=");
+ TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
+ sb.append(" s=");
+ TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
+ Slog.d(TAG, sb.toString());
+ }
+
+ final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
+ u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
+ u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
+
+ final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
+ proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs,
+ (int) mTempTotalCpuSystemTimeUs);
+ }
+ }
+
+ // See if there is a difference in wakelocks between this collection and the last
+ // collection.
+ if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
+ // No difference, so each timer is now considered for the next collection.
+ for (int i = 0; i < numPartialTimers; i++) {
+ mPartialTimers.get(i).mInList = true;
+ }
+ } else {
+ // The lists are different, meaning we added (or removed a timer) since the last
+ // collection.
+ final int numLastPartialTimers = mLastPartialTimers.size();
+ for (int i = 0; i < numLastPartialTimers; i++) {
+ mLastPartialTimers.get(i).mInList = false;
+ }
+ mLastPartialTimers.clear();
+
+ // Mark the current timers as gone through a collection.
+ for (int i = 0; i < numPartialTimers; i++) {
+ final StopwatchTimer timer = mPartialTimers.get(i);
+ timer.mInList = true;
+ mLastPartialTimers.add(timer);
+ }
+ }
}
boolean setChargingLocked(boolean charging) {
@@ -8157,6 +8246,12 @@
}
}
+ private void scheduleSyncExternalWifiStatsLocked(String reason) {
+ if (mExternalSync != null) {
+ mExternalSync.scheduleWifiSync(reason);
+ }
+ }
+
// This should probably be exposed in the API, though it's not critical
public static final int BATTERY_PLUGGED_NONE = 0;
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index b236378..62926d1 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -16,9 +16,11 @@
package com.android.internal.os;
import android.annotation.Nullable;
+import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseLongArray;
+import android.util.TimeUtils;
import java.io.BufferedReader;
import java.io.FileReader;
@@ -49,6 +51,7 @@
private SparseLongArray mLastUserTimeUs = new SparseLongArray();
private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
+ private long mLastTimeRead = 0;
/**
* Reads the proc file, calling into the callback with a delta of time for each UID.
@@ -57,6 +60,7 @@
* a fresh delta.
*/
public void readDelta(@Nullable Callback callback) {
+ long now = SystemClock.elapsedRealtime();
try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) {
TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
String line;
@@ -75,10 +79,32 @@
userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
- if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) {
- // The UID must have been removed from accounting, then added back.
- userTimeDeltaUs = userTimeUs;
- systemTimeDeltaUs = systemTimeUs;
+ final long timeDiffMs = (now - mLastTimeRead) * 1000;
+ if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 ||
+ userTimeDeltaUs > timeDiffMs || systemTimeDeltaUs > timeDiffMs ) {
+ StringBuilder sb = new StringBuilder("Malformed cpu data!\n");
+ sb.append("Time between reads: ");
+ TimeUtils.formatDuration(timeDiffMs, sb);
+ sb.append("ms\n");
+ sb.append("Previous times: u=");
+ TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
+ sb.append("ms s=");
+ TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
+ sb.append("ms\n");
+ sb.append("Current times: u=");
+ TimeUtils.formatDuration(userTimeUs / 1000, sb);
+ sb.append("ms s=");
+ TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+ sb.append("ms\n");
+ sb.append("Delta for UID=").append(uid).append(": u=");
+ TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
+ sb.append("ms s=");
+ TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
+ sb.append("ms");
+ Slog.wtf(TAG, sb.toString());
+
+ userTimeDeltaUs = 0;
+ systemTimeDeltaUs = 0;
}
}
@@ -92,6 +118,7 @@
} catch (IOException e) {
Slog.e(TAG, "Failed to read uid_cputime", e);
}
+ mLastTimeRead = now;
}
/**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 4f6d781..c97fdf4 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -41,8 +41,8 @@
public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
/** enable the JIT compiler */
public static final int DEBUG_ENABLE_JIT = 1 << 5;
- /** Force generation of CFI code */
- public static final int DEBUG_GENERATE_CFI = 1 << 6;
+ /** Force generation of native debugging information. */
+ public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 6;
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = 0;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 1a0345b..fa870b9 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -322,7 +322,7 @@
/**
* From --enable-debugger, --enable-checkjni, --enable-assert,
- * --enable-safemode, --enable-jit, --generate-cfi and --enable-jni-logging.
+ * --enable-safemode, --enable-jit, --generate-debug-info and --enable-jni-logging.
*/
int debugFlags;
@@ -434,8 +434,8 @@
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
} else if (arg.equals("--enable-jit")) {
debugFlags |= Zygote.DEBUG_ENABLE_JIT;
- } else if (arg.equals("--generate-cfi")) {
- debugFlags |= Zygote.DEBUG_GENERATE_CFI;
+ } else if (arg.equals("--generate-debug-info")) {
+ debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
} else if (arg.equals("--enable-jni-logging")) {
debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
} else if (arg.equals("--enable-assert")) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 66f6079..15ed5bd 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3223,12 +3223,11 @@
cb.onWindowFocusChanged(hasWindowFocus);
}
- if (mFloatingToolbar != null) {
- if (hasWindowFocus) {
- mFloatingToolbar.show();
- } else {
- mFloatingToolbar.dismiss();
- }
+ if (mPrimaryActionMode != null) {
+ mPrimaryActionMode.onWindowFocusChanged(hasWindowFocus);
+ }
+ if (mFloatingActionMode != null) {
+ mFloatingActionMode.onWindowFocusChanged(hasWindowFocus);
}
}
@@ -3441,8 +3440,7 @@
mFloatingActionMode = mode;
mFloatingToolbar = new FloatingToolbar(mContext, PhoneWindow.this);
((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
- mFloatingActionMode.invalidate();
- mFloatingToolbar.show();
+ mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary.
mFloatingActionModeOriginatingView.getViewTreeObserver()
.addOnPreDrawListener(mFloatingToolbarPreDrawListener);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 9f99f62..0732add 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -64,5 +64,7 @@
* bar caused by this app transition in millis
*/
void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
+
+ void showAssistDisclosure();
}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 62e724a..9d0636a 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -387,4 +387,26 @@
public static <T> boolean contains(ArrayList<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
+
+ /**
+ * Returns true if the two ArrayLists are equal with respect to the objects they contain.
+ * The objects must be in the same order and be reference equal (== not .equals()).
+ */
+ public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) {
+ if (a == b) {
+ return true;
+ }
+
+ final int sizeA = a.size();
+ final int sizeB = b.size();
+ if (a == null || b == null || sizeA != sizeB) {
+ return false;
+ }
+
+ boolean diff = false;
+ for (int i = 0; i < sizeA && !diff; i++) {
+ diff |= a.get(i) != b.get(i);
+ }
+ return !diff;
+ }
}
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 784b256..863506b 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -197,6 +197,13 @@
}
@Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ checkToolbarInitialized();
+ mFloatingToolbarVisibilityHelper.setWindowFocused(hasWindowFocus);
+ mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
+ }
+
+ @Override
public void finish() {
checkToolbarInitialized();
reset();
@@ -237,6 +244,7 @@
}
private void reset() {
+ mFloatingToolbar.dismiss();
mFloatingToolbarVisibilityHelper.deactivate();
mOriginatingView.removeCallbacks(mMovingOff);
mOriginatingView.removeCallbacks(mHideOff);
@@ -253,6 +261,7 @@
private boolean mHideRequested;
private boolean mMoving;
private boolean mOutOfBounds;
+ private boolean mWindowFocused = true;
private boolean mActive;
@@ -264,6 +273,7 @@
mHideRequested = false;
mMoving = false;
mOutOfBounds = false;
+ mWindowFocused = true;
mActive = true;
}
@@ -285,12 +295,16 @@
mOutOfBounds = outOfBounds;
}
+ public void setWindowFocused(boolean windowFocused) {
+ mWindowFocused = windowFocused;
+ }
+
public void updateToolbarVisibility() {
if (!mActive) {
return;
}
- if (mHideRequested || mMoving || mOutOfBounds) {
+ if (mHideRequested || mMoving || mOutOfBounds || !mWindowFocused) {
mToolbar.hide();
} else {
mToolbar.show();
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index e19b2b6..85ec29c 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -409,8 +409,8 @@
}
case DO_REPORT_FULLSCREEN_MODE: {
InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "showStatusIcon on inactive InputConnection");
+ if (ic == null) {
+ Log.w(TAG, "reportFullscreenMode on inexistent InputConnection");
return;
}
ic.reportFullscreenMode(msg.arg1 == 1);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 65f2f53f..523663c 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -546,25 +546,25 @@
private void refreshCoordinatesAndOverflowDirection(Rect contentRect) {
refreshViewPort();
- int availableHeightAboveContent =
- contentRect.top - mViewPort.top - 2 * mMarginVertical;
- int availableHeightBelowContent =
- mViewPort.bottom - contentRect.bottom - 2 * mMarginVertical;
- int availableHeightThroughContent =
- mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin();
-
int x = contentRect.centerX() - getWidth() / 2;
// Update x so that the toolbar isn't rendered behind the nav bar in landscape.
x = Math.max(0, Math.min(x, mViewPort.right - getWidth()));
int y;
+
+ int availableHeightAboveContent = contentRect.top - mViewPort.top;
+ int availableHeightBelowContent = mViewPort.bottom - contentRect.bottom;
+
if (mOverflowPanel == null) { // There is no overflow.
- if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin()) {
+ if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin()) {
// There is enough space at the top of the content.
y = contentRect.top - getToolbarHeightWithVerticalMargin();
- } else if (availableHeightBelowContent > getToolbarHeightWithVerticalMargin()) {
+ } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin()) {
// There is enough space at the bottom of the content.
y = contentRect.bottom;
+ } else if (availableHeightBelowContent >= getEstimatedToolbarHeight(getContext())) {
+ // Just enough space to fit the toolbar with no vertical margins.
+ y = contentRect.bottom - mMarginVertical;
} else {
// Not enough space. Prefer to position as high as possible.
y = Math.max(
@@ -572,32 +572,47 @@
contentRect.top - getToolbarHeightWithVerticalMargin());
}
} else { // There is an overflow.
- if (availableHeightAboveContent > mOverflowPanel.getMinimumHeight()) {
+ int margin = 2 * mMarginVertical;
+ int minimumOverflowHeightWithMargin = mOverflowPanel.getMinimumHeight() + margin;
+ int availableHeightThroughContentDown =
+ mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin();
+ int availableHeightThroughContentUp =
+ contentRect.bottom - mViewPort.top + getToolbarHeightWithVerticalMargin();
+
+ if (availableHeightAboveContent >= minimumOverflowHeightWithMargin) {
// There is enough space at the top of the content rect for the overflow.
// Position above and open upwards.
- updateOverflowHeight(availableHeightAboveContent);
+ updateOverflowHeight(availableHeightAboveContent - margin);
y = contentRect.top - getHeight();
mOverflowDirection = OVERFLOW_DIRECTION_UP;
- } else if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin()
- && availableHeightThroughContent > mOverflowPanel.getMinimumHeight()) {
+ } else if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin()
+ && availableHeightThroughContentDown >= minimumOverflowHeightWithMargin) {
// There is enough space at the top of the content rect for the main panel
// but not the overflow.
// Position above but open downwards.
- updateOverflowHeight(availableHeightThroughContent);
+ updateOverflowHeight(availableHeightThroughContentDown - margin);
y = contentRect.top - getToolbarHeightWithVerticalMargin();
mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
- } else if (availableHeightBelowContent > mOverflowPanel.getMinimumHeight()) {
+ } else if (availableHeightBelowContent >= minimumOverflowHeightWithMargin) {
// There is enough space at the bottom of the content rect for the overflow.
// Position below and open downwards.
- updateOverflowHeight(availableHeightBelowContent);
+ updateOverflowHeight(availableHeightBelowContent - margin);
y = contentRect.bottom;
mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
+ } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin()
+ && mViewPort.height() >= minimumOverflowHeightWithMargin) {
+ // There is enough space at the bottom of the content rect for the main panel
+ // but not the overflow.
+ // Position below but open upwards.
+ updateOverflowHeight(availableHeightThroughContentUp - margin);
+ y = contentRect.bottom + getToolbarHeightWithVerticalMargin() - getHeight();
+ mOverflowDirection = OVERFLOW_DIRECTION_UP;
} else {
// Not enough space.
- // Position at the bottom of the view port and open upwards.
- updateOverflowHeight(mViewPort.height());
- y = mViewPort.bottom - getHeight();
- mOverflowDirection = OVERFLOW_DIRECTION_UP;
+ // Position at the top of the view port and open downwards.
+ updateOverflowHeight(mViewPort.height() - margin);
+ y = mViewPort.top;
+ mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
}
mOverflowPanel.setOverflowDirection(mOverflowDirection);
}
@@ -1422,7 +1437,6 @@
PopupWindow popupWindow = new PopupWindow(popupContentHolder);
popupWindow.setWindowLayoutType(
WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
- popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
popupWindow.setAnimationStyle(0);
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
content.setLayoutParams(new ViewGroup.LayoutParams(
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 7c2b28d..2c35a8b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -876,16 +876,16 @@
"-Xzygote-max-boot-retry=");
/*
- * When running with debug.gencfi, add --include-cfi to the compiler options so that the boot
- * image, if it is compiled on device, will include CFI info, as well as other compilations
- * started by the runtime.
+ * When running with debug.generate-debug-info, add --generate-debug-info to
+ * the compiler options so that the boot image, if it is compiled on device,
+ * will include native debugging information.
*/
- property_get("debug.gencfi", propBuf, "");
+ property_get("debug.generate-debug-info", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
addOption("-Xcompiler-option");
- addOption("--include-cfi");
+ addOption("--generate-debug-info");
addOption("-Ximage-compiler-option");
- addOption("--include-cfi");
+ addOption("--generate-debug-info");
}
initArgs.version = JNI_VERSION_1_4;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7272ae3..424a0b7 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2031,10 +2031,8 @@
string that's stored in 8-bit unpacked format) characters.-->
<bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool>
- <!-- List of package names (ordered by preference) providing WebView implementations. -->
- <string-array name="config_webViewPackageNames" translatable="false">
- <item>com.android.webview</item>
- </string-array>
+ <!-- Package name providing WebView implementation. -->
+ <string name="config_webViewPackageName" translatable="false">com.android.webview</string>
<!-- If EMS is not supported, framework breaks down EMS into single segment SMS
and adds page info " x/y". This config is used to set which carrier doesn't
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4160e0e..295251c 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2018,7 +2018,7 @@
<java-symbol type="attr" name="actionModeWebSearchDrawable" />
<java-symbol type="string" name="websearch" />
<java-symbol type="drawable" name="ic_media_video_poster" />
- <java-symbol type="array" name="config_webViewPackageNames" />
+ <java-symbol type="string" name="config_webViewPackageName" />
<!-- From SubtitleView -->
<java-symbol type="dimen" name="subtitle_corner_radius" />
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 9a834506..7b1169f 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -30,21 +30,22 @@
-sdk.linux_download=android-sdk_r24.3.2-linux.tgz
-sdk.linux_bytes=309138263
-sdk.linux_checksum=4a10e62c5d88fd6c2a69db12348cbe168228b98f
+sdk.linux_download=android-sdk_r24.3.3-linux.tgz
+sdk.linux_bytes=309109716
+sdk.linux_checksum=cd4cab76c2e3d926b3495c26ec56c831ba77d0d0
-sdk.mac_download=android-sdk_r24.3.2-macosx.zip
-sdk.mac_bytes=98329772
-sdk.mac_checksum=8609b92e26e9bd5796f771138c6b222b6c0cb474
+sdk.mac_download=android-sdk_r24.3.3-macosx.zip
+sdk.mac_bytes=98330824
+sdk.mac_checksum=41f0f3e76d6868018740e654aefb04fd765c357d
-sdk.win_download=android-sdk_r24.3.2-windows.zip
-sdk.win_bytes=187488291
-sdk.win_checksum=bcfe3c41ea7e33a29ad6f358adbdf977008be80a
+sdk.win_download=android-sdk_r24.3.3-windows.zip
+sdk.win_bytes=187480692
+sdk.win_checksum=b6a4899efbf20fc593042f1515446c6630ba502e
-sdk.win_installer=installer_r24.3.2-windows.exe
-sdk.win_installer_bytes=139471724
-sdk.win_installer_checksum=8f9d0ae9fdb37973ed62d6e93975ff375beb5542
+
+sdk.win_installer=installer_r24.3.3-windows.exe
+sdk.win_installer_bytes=139463749
+sdk.win_installer_checksum=bbdae40a7665e55b3cdb1fbae865986e6cd3df14
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 326fbe2..934b262 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -25,6 +25,36 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>SDK Tools, Revision 24.3.3</a> <em>(June 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 19 or later.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed issues with using Ant build tasks with the Eclipse ADT build structure. </li>
+ <li>Fixed the emulator boot problem on Mac OS X 10.8.5.</li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>SDK Tools, Revision 24.3.2</a> <em>(June 2015)</em>
</p>
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 9acfee2..ab61e2b 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -89,10 +89,23 @@
* encrypted content, the samples returned from the extractor remain encrypted, they
* are only decrypted when the samples are delivered to the decoder.
* <p>
- * MediaDrm methods throw {@link java.lang.IllegalStateException}
- * when a method is called on a MediaDrm object that is in an invalid or inoperable
- * state. This is typically due to incorrect application API usage, but may also
- * be due to an unrecoverable failure in the DRM plugin or security hardware.
+ * MediaDrm methods throw {@link android.media.MediaDrm.MediaDrmStateException}
+ * when a method is called on a MediaDrm object that has had an unrecoverable failure
+ * in the DRM plugin or security hardware.
+ * {@link android.media.MediaDrm.MediaDrmStateException} extends
+ * {@link java.lang.IllegalStateException} with the addition of a developer-readable
+ * diagnostic information string associated with the exception.
+ * <p>
+ * In the event of a mediaserver process crash or restart while a MediaDrm object
+ * is active, MediaDrm methods may throw {@link android.media.MediaDrmResetException}.
+ * To recover, the app must release the MediaDrm object, then create and initialize
+ * a new one.
+ * <p>
+ * As {@link android.media.MediaDrmResetException} and
+ * {@link android.media.MediaDrm.MediaDrmStateException} both extend
+ * {@link java.lang.IllegalStateException}, they should be in an earlier catch()
+ * block than {@link java.lang.IllegalStateException} if handled separately.
+ * <p>
* <a name="Callbacks"></a>
* <h3>Callbacks</h3>
* <p>Applications should register for informational events in order
diff --git a/media/java/android/media/MediaDrmResetException.java b/media/java/android/media/MediaDrmResetException.java
new file mode 100644
index 0000000..3b2da1e
--- /dev/null
+++ b/media/java/android/media/MediaDrmResetException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 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.media;
+
+/**
+ * This exception is thrown when the MediaDrm instance has become unusable
+ * due to a restart of the mediaserver process. To continue, the app must
+ * release the MediaDrm object, then create and initialize a new one.
+ */
+public class MediaDrmResetException extends IllegalStateException {
+ public MediaDrmResetException(String detailMessage) {
+ super(detailMessage);
+ }
+}
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index d456dc10..9ec0312 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -308,6 +308,10 @@
} else if (err == ERROR_DRM_DEVICE_REVOKED) {
jniThrowException(env, "android/media/DeniedByServerException", msg);
return true;
+ } else if (err == DEAD_OBJECT) {
+ jniThrowException(env, "android/media/MediaDrmResetException",
+ "mediaserver died");
+ return true;
} else if (err != OK) {
String8 errbuf;
if (drmMessage != NULL) {
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index fdc586b..aba4bbe 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -472,6 +472,8 @@
if (lpJniStorage) {
ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_class);
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_ref);
delete lpJniStorage;
}
}
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 6098b4a..0557019 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -450,6 +450,8 @@
if (lpJniStorage) {
ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class);
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref);
delete lpJniStorage;
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index aa99a7b..0c6837f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -216,6 +216,19 @@
return mCallback;
}
+ @Override
+ public void showPromptReason(int reason) {
+ if (reason != PROMPT_REASON_NONE) {
+ int promtReasonStringRes = getPromtReasonStringRes(reason);
+ if (promtReasonStringRes != 0) {
+ mSecurityMessageDisplay.setMessage(promtReasonStringRes,
+ true /* important */);
+ }
+ }
+ }
+
+ protected abstract int getPromtReasonStringRes(int reason);
+
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
if (mEnableHaptics) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index cd4b24a..ff4e815 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -160,6 +160,17 @@
}
/**
+ * Show a string explaining why the security view needs to be solved.
+ *
+ * @param reason a flag indicating which string should be shown, see
+ * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+ * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
+ */
+ public void showPromptReason(int reason) {
+ mSecurityContainer.showPromptReason(reason);
+ }
+
+ /**
* Dismisses the keyguard by going to the next screen or making it gone.
*
* @return True if the keyguard is done.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index c9ad728..2db87b3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -111,6 +111,16 @@
}
@Override
+ protected int getPromtReasonStringRes(int reason) {
+ switch (reason) {
+ case PROMPT_REASON_RESTART:
+ return R.string.kg_prompt_reason_restart_password;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
public void onPause() {
super.onPause();
mImm.hideSoftInputFromWindow(getWindowToken(), 0);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 1bd0bb4..59a8ad5 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -85,10 +85,9 @@
}
};
private Rect mTempRect = new Rect();
- private SecurityMessageDisplay mSecurityMessageDisplay;
+ private KeyguardMessageArea mSecurityMessageDisplay;
private View mEcaView;
private ViewGroup mContainer;
- private KeyguardMessageArea mHelpMessage;
private int mDisappearYTranslation;
enum FooterMode {
@@ -141,10 +140,10 @@
// vibrate mode will be the same for the life of this screen
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
- mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
+ mSecurityMessageDisplay =
+ (KeyguardMessageArea) KeyguardMessageArea.findSecurityMessageDisplay(this);
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
mContainer = (ViewGroup) findViewById(R.id.container);
- mHelpMessage = (KeyguardMessageArea) findViewById(R.id.keyguard_message_area);
EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
if (button != null) {
@@ -320,6 +319,17 @@
}
@Override
+ public void showPromptReason(int reason) {
+ switch (reason) {
+ case PROMPT_REASON_RESTART:
+ mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_restart_pattern,
+ true /* important */);
+ break;
+ default:
+ }
+ }
+
+ @Override
public void startAppearAnimation() {
enableClipping(false);
setAlpha(1f);
@@ -337,8 +347,8 @@
}
},
this);
- if (!TextUtils.isEmpty(mHelpMessage.getText())) {
- mAppearAnimationUtils.createAnimation(mHelpMessage, 0,
+ if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
+ mAppearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
AppearAnimationUtils.DEFAULT_APPEAR_DURATION,
mAppearAnimationUtils.getStartTranslation(),
true /* appearing */,
@@ -366,8 +376,8 @@
}
}
}, KeyguardPatternView.this);
- if (!TextUtils.isEmpty(mHelpMessage.getText())) {
- mDisappearAnimationUtils.createAnimation(mHelpMessage, 0,
+ if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
+ mDisappearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
200,
- mDisappearAnimationUtils.getStartTranslation() * 3,
false /* appearing */,
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 23834a3..07947b1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -93,6 +93,16 @@
return super.onKeyDown(keyCode, event);
}
+ @Override
+ protected int getPromtReasonStringRes(int reason) {
+ switch (reason) {
+ case PROMPT_REASON_RESTART:
+ return R.string.kg_prompt_reason_restart_pin;
+ default:
+ return 0;
+ }
+ }
+
private void performClick(View view) {
view.performClick();
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index d17b25a..f529ac0 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -509,6 +509,13 @@
}
@Override
+ public void showPromptReason(int reason) {
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
+ }
+ }
+
+ @Override
public void showUsabilityHint() {
mSecurityViewFlipper.showUsabilityHint();
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
index 5b50236..5658a74 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
@@ -21,6 +21,9 @@
static public final int SCREEN_ON = 1;
static public final int VIEW_REVEALED = 2;
+ int PROMPT_REASON_NONE = 0;
+ int PROMPT_REASON_RESTART = 1;
+
/**
* Interface back to keyguard to tell it when security
* @param callback
@@ -66,6 +69,14 @@
KeyguardSecurityCallback getCallback();
/**
+ * Show a string explaining why the security view needs to be solved.
+ *
+ * @param reason a flag indicating which string should be shown, see {@link #PROMPT_REASON_NONE}
+ * and {@link #PROMPT_REASON_RESTART}
+ */
+ void showPromptReason(int reason);
+
+ /**
* Instruct the view to show usability hints, if any.
*
*/
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 54467f3..a0ff21b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -131,6 +131,14 @@
}
@Override
+ public void showPromptReason(int reason) {
+ KeyguardSecurityView ksv = getSecurityView();
+ if (ksv != null) {
+ ksv.showPromptReason(reason);
+ }
+ }
+
+ @Override
public void showUsabilityHint() {
KeyguardSecurityView ksv = getSecurityView();
if (ksv != null) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index f4acff8..aeac912 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -95,6 +95,12 @@
}
}
+ @Override
+ protected int getPromtReasonStringRes(int reason) {
+ // No message on SIM Pin
+ return 0;
+ }
+
private String getPinPasswordErrorMessage(int attemptsRemaining) {
String displayMessage;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index b85d966..af88239 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -140,6 +140,12 @@
}
}
+ @Override
+ protected int getPromtReasonStringRes(int reason) {
+ // No message on SIM Puk
+ return 0;
+ }
+
private String getPukPasswordErrorMessage(int attemptsRemaining) {
String displayMessage;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 273f166..022338d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -804,8 +804,7 @@
private void startListeningForFingerprint() {
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
- if (mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
- && mFpm.getEnrolledFingerprints(userId).size() > 0) {
+ if (isUnlockWithFingerPrintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}
@@ -815,6 +814,11 @@
}
}
+ public boolean isUnlockWithFingerPrintPossible(int userId) {
+ return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
+ && mFpm.getEnrolledFingerprints(userId).size() > 0;
+ }
+
private void stopListeningForFingerprint() {
if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
if (isFingerprintDetectionRunning()) {
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index f5c809a..ff463c6 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -81,4 +81,12 @@
* @return true if the screen is on
*/
boolean isScreenOn();
+
+ /**
+ * @return one of the reasons why the bouncer needs to be shown right now and the user can't use
+ * his normal unlock method like fingerprint or trust agents. See
+ * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+ * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}.
+ */
+ int getBouncerPromptReason();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index b0429ef..249eaa5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -808,7 +808,7 @@
// The pairing dialog now warns of phone-book access for paired devices.
// No separate prompt is displayed after pairing.
if (getPhonebookPermissionChoice() == CachedBluetoothDevice.ACCESS_UNKNOWN) {
- setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_ALLOWED);
+ setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_REJECTED);
}
}
}
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index 13747ed..0c84fa1 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -27,6 +27,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.FileUtils;
@@ -77,21 +78,12 @@
@Override
public void onReceive(Context context, Intent intent) {
+ final Configuration conf = context.getResources().getConfiguration();
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
- // Files are kept on private storage, so turn into Uris that we can
- // grant temporary permissions for.
- final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
- final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
-
- boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
- if (!isPlainText) {
- // Already zipped, send it right away.
- sendBugreportNotification(context, bugreportFile, screenshotFile);
- } else {
- // Asynchronously zip the file first, then send it.
- sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
+ if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
+ triggerLocalNotification(context, bugreportFile, screenshotFile);
}
// Clean up older bugreports in background
@@ -107,6 +99,29 @@
}.execute();
}
+ /**
+ * Responsible for triggering a notification that allows the user to start a
+ * "share" intent with the bug report. On watches we have other methods to allow the user to
+ * start this intent (usually by triggering it on another connected device); we don't need to
+ * display the notification in this case.
+ */
+ private void triggerLocalNotification(final Context context, final File bugreportFile,
+ final File screenshotFile) {
+ // Files are kept on private storage, so turn into Uris that we can
+ // grant temporary permissions for.
+ final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
+ final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
+
+ boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
+ if (!isPlainText) {
+ // Already zipped, send it right away.
+ sendBugreportNotification(context, bugreportFile, screenshotFile);
+ } else {
+ // Asynchronously zip the file first, then send it.
+ sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
+ }
+ }
+
private static Intent buildWarningIntent(Context context, Intent sendIntent) {
final Intent intent = new Intent(context, BugreportWarningActivity.class);
intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
diff --git a/packages/SystemUI/res/drawable/managed_profile_toast_background.xml b/packages/SystemUI/res/drawable/managed_profile_toast_background.xml
deleted file mode 100644
index 5c77b9a..0000000
--- a/packages/SystemUI/res/drawable/managed_profile_toast_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <corners android:radius="2dp" />
- <solid android:color="@color/managed_profile_toast_background" />
-</shape>
diff --git a/packages/SystemUI/res/layout/managed_profile_toast.xml b/packages/SystemUI/res/layout/managed_profile_toast.xml
deleted file mode 100644
index 5a01ca7..0000000
--- a/packages/SystemUI/res/layout/managed_profile_toast.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
- android:background="@drawable/managed_profile_toast_background">
- <ImageView
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="16dp"
- android:src="@drawable/stat_sys_managed_profile_status"/>
- <TextView android:text="@string/managed_profile_foreground_toast"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@android:color/white"
- android:textSize="14sp"
- android:layout_gravity="center_horizontal" />
-</LinearLayout>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9a96939..0dcbe88 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -143,6 +143,4 @@
<color name="volume_icon_color">#ffffffff</color>
<color name="volume_settings_icon_color">#7fffffff</color>
<color name="volume_slider_inactive">#FFB0BEC5</color><!-- blue grey 200 -->
-
- <color name="managed_profile_toast_background">#E5000000</color><!-- 90% black -->
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b0e71f9..869b03a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -575,4 +575,13 @@
<!-- Standard image button size for volume dialog buttons -->
<dimen name="volume_button_size">48dp</dimen>
+
+ <!-- Padding between icon and text for managed profile toast -->
+ <dimen name="managed_profile_toast_padding">4dp</dimen>
+
+ <!-- Thickness of the assist disclosure beams -->
+ <dimen name="assist_disclosure_thickness">4dp</dimen>
+
+ <!-- Thickness of the shadows of the assist disclosure beams -->
+ <dimen name="assist_disclosure_shadow_thickness">1.5dp</dimen>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
new file mode 100644
index 0000000..234a699
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -0,0 +1,251 @@
+/*
+ * 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.assist;
+
+import com.android.systemui.R;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.os.Handler;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.animation.AnimationUtils;
+
+/**
+ * Visually discloses that contextual data was provided to an assistant.
+ */
+public class AssistDisclosure {
+ private final Context mContext;
+ private final WindowManager mWm;
+ private final Handler mHandler;
+
+ private AssistDisclosureView mView;
+ private boolean mViewAdded;
+
+ public AssistDisclosure(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ mWm = mContext.getSystemService(WindowManager.class);
+ }
+
+ public void postShow() {
+ mHandler.removeCallbacks(mShowRunnable);
+ mHandler.post(mShowRunnable);
+ }
+
+ private void show() {
+ if (mView == null) {
+ mView = new AssistDisclosureView(mContext);
+ }
+ if (!mViewAdded) {
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_FULLSCREEN
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
+ PixelFormat.TRANSLUCENT);
+ lp.setTitle("AssistDisclosure");
+
+ mWm.addView(mView, lp);
+ mViewAdded = true;
+ }
+ }
+
+ private void hide() {
+ if (mViewAdded) {
+ mWm.removeView(mView);
+ mViewAdded = false;
+ }
+ }
+
+ private Runnable mShowRunnable = new Runnable() {
+ @Override
+ public void run() {
+ show();
+ }
+ };
+
+ private class AssistDisclosureView extends View
+ implements ValueAnimator.AnimatorUpdateListener {
+
+ public static final int TRACING_ANIMATION_DURATION = 300;
+ public static final int ALPHA_ANIMATION_DURATION = 200;
+
+ private float mThickness;
+ private float mShadowThickness;
+ private final Paint mPaint = new Paint();
+ private final Paint mShadowPaint = new Paint();
+
+ private final ValueAnimator mTracingAnimator;
+ private final ValueAnimator mAlphaAnimator;
+ private final AnimatorSet mAnimator;
+
+ private float mTracingProgress = 0;
+ private int mAlpha = 255;
+
+ public AssistDisclosureView(Context context) {
+ super(context);
+
+ mTracingAnimator = ValueAnimator.ofFloat(0, 1).setDuration(TRACING_ANIMATION_DURATION);
+ mTracingAnimator.addUpdateListener(this);
+ mTracingAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.fast_out_slow_in));
+ mAlphaAnimator = ValueAnimator.ofInt(255, 0).setDuration(ALPHA_ANIMATION_DURATION);
+ mAlphaAnimator.addUpdateListener(this);
+ mAlphaAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.fast_out_linear_in));
+ mAnimator = new AnimatorSet();
+ mAnimator.play(mTracingAnimator).before(mAlphaAnimator);
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ boolean mCancelled;
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mCancelled = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCancelled) {
+ hide();
+ }
+ }
+ });
+
+ PorterDuffXfermode srcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
+ mPaint.setColor(Color.WHITE);
+ mPaint.setXfermode(srcMode);
+ mShadowPaint.setColor(Color.DKGRAY);
+ mShadowPaint.setXfermode(srcMode);
+
+ mThickness = getResources().getDimension(R.dimen.assist_disclosure_thickness);
+ mShadowThickness = getResources().getDimension(
+ R.dimen.assist_disclosure_shadow_thickness);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ startAnimation();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ mAnimator.cancel();
+
+ mTracingProgress = 0;
+ mAlpha = 255;
+ }
+
+ private void startAnimation() {
+ mAnimator.cancel();
+ mAnimator.start();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ mPaint.setAlpha(mAlpha);
+ mShadowPaint.setAlpha(mAlpha / 4);
+
+ drawGeometry(canvas, mShadowPaint, mShadowThickness);
+ drawGeometry(canvas, mPaint, 0);
+ }
+
+ private void drawGeometry(Canvas canvas, Paint paint, float padding) {
+ final int width = getWidth();
+ final int height = getHeight();
+ float thickness = mThickness;
+ final float pixelProgress = mTracingProgress * (width + height - 2 * thickness);
+
+ float bottomProgress = Math.min(pixelProgress, width / 2f);
+ if (bottomProgress > 0) {
+ drawBeam(canvas,
+ width / 2f - bottomProgress,
+ height - thickness,
+ width / 2f + bottomProgress,
+ height, paint, padding);
+ }
+
+ float sideProgress = Math.min(pixelProgress - bottomProgress, height - thickness);
+ if (sideProgress > 0) {
+ drawBeam(canvas,
+ 0,
+ (height - thickness) - sideProgress,
+ thickness,
+ height - thickness, paint, padding);
+ drawBeam(canvas,
+ width - thickness,
+ (height - thickness) - sideProgress,
+ width,
+ height - thickness, paint, padding);
+ }
+
+ float topProgress = Math.min(pixelProgress - bottomProgress - sideProgress,
+ width / 2 - thickness);
+ if (sideProgress > 0 && topProgress > 0) {
+ drawBeam(canvas,
+ thickness,
+ 0,
+ thickness + topProgress,
+ thickness, paint, padding);
+ drawBeam(canvas,
+ (width - thickness) - topProgress,
+ 0,
+ width - thickness,
+ thickness, paint, padding);
+ }
+ }
+
+ private void drawBeam(Canvas canvas, float left, float top, float right, float bottom,
+ Paint paint, float padding) {
+ canvas.drawRect(left - padding,
+ top - padding,
+ right + padding,
+ bottom + padding,
+ paint);
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (animation == mAlphaAnimator) {
+ mAlpha = (int) mAlphaAnimator.getAnimatedValue();
+ } else if (animation == mTracingAnimator) {
+ mTracingProgress = (float) mTracingAnimator.getAnimatedValue();
+ }
+ invalidate();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 445ecb6..674356b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -55,6 +55,8 @@
private final Context mContext;
private final WindowManager mWindowManager;
+ private final AssistDisclosure mAssistDisclosure;
+
private AssistOrbContainer mView;
private final PhoneStatusBar mBar;
private final AssistUtils mAssistUtils;
@@ -100,6 +102,7 @@
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false,
mAssistSettingsObserver);
mAssistSettingsObserver.onChange(false);
+ mAssistDisclosure = new AssistDisclosure(context, new Handler());
}
public void onConfigurationChanged() {
@@ -187,8 +190,11 @@
mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL |
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL);
+ boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
+
final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, structureEnabled, UserHandle.USER_CURRENT);
if (intent == null) {
return;
}
@@ -196,6 +202,10 @@
intent.setComponent(mAssistComponent);
}
+ if (structureEnabled) {
+ showDisclosure();
+ }
+
try {
final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.search_launch_enter, R.anim.search_launch_exit);
@@ -297,4 +307,8 @@
pw.println("AssistManager state:");
pw.print(" mAssistComponent="); pw.println(mAssistComponent);
}
+
+ public void showDisclosure() {
+ mAssistDisclosure.postShow();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c06b34f..80761d8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -62,6 +62,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardDisplayManager;
+import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
@@ -526,6 +527,17 @@
public boolean isScreenOn() {
return mDeviceInteractive;
}
+
+ @Override
+ public int getBouncerPromptReason() {
+ int currentUser = ActivityManager.getCurrentUser();
+ if ((mUpdateMonitor.getUserTrustIsManaged(currentUser)
+ || mUpdateMonitor.isUnlockWithFingerPrintPossible(currentUser))
+ && !mTrustManager.hasUserAuthenticatedSinceBoot(currentUser)) {
+ return KeyguardSecurityView.PROMPT_REASON_RESTART;
+ }
+ return KeyguardSecurityView.PROMPT_REASON_NONE;
+ }
};
public void userActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 9761cd1..4b1453d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -390,7 +390,7 @@
mDetailSettingsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- mHost.startSettingsActivity(settingsIntent);
+ mHost.startActivityDismissingKeyguard(settingsIntent);
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 72bb136..38fade2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -306,7 +306,7 @@
}
public interface Host {
- void startSettingsActivity(Intent intent);
+ void startActivityDismissingKeyguard(Intent intent);
void warn(String message, Throwable t);
void collapsePanels();
Looper getLooper();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index a9e8b38..07406b9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -82,7 +82,7 @@
if (mDataController.isMobileDataSupported()) {
showDetail(true);
} else {
- mHost.startSettingsActivity(CELLULAR_SETTINGS);
+ mHost.startActivityDismissingKeyguard(CELLULAR_SETTINGS);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index f97f519..1b74eb6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -263,7 +263,7 @@
private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
@Override
public void onPrioritySettings() {
- mHost.startSettingsActivity(ZEN_PRIORITY_SETTINGS);
+ mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 19f4df6..f7f7acb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -96,7 +96,11 @@
private void sendIntent(String type, PendingIntent pi, String uri) {
try {
if (pi != null) {
- pi.send();
+ if (pi.isActivity()) {
+ getHost().startActivityDismissingKeyguard(pi.getIntent());
+ } else {
+ pi.send();
+ }
} else if (uri != null) {
final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 9bc5b75..c33ef7c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -104,7 +104,7 @@
@Override
protected void handleSecondaryClick() {
if (!mWifiController.canConfigWifi()) {
- mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
+ mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_WIFI_SETTINGS));
return;
}
if (!mState.enabled) {
@@ -290,7 +290,7 @@
@Override
public void onSettingsActivityTriggered(Intent settingsIntent) {
- mHost.startSettingsActivity(settingsIntent);
+ mHost.startActivityDismissingKeyguard(settingsIntent);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a496548..295fdc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -393,13 +393,16 @@
if (recentTask != null && recentTask.size() > 0) {
UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId);
if (user != null && user.isManagedProfile()) {
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- View layout = inflater.inflate(R.layout.managed_profile_toast, null);
- Toast toast = new Toast(mContext);
- toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
- toast.setDuration(Toast.LENGTH_SHORT);
- toast.setView(layout);
+ Toast toast = Toast.makeText(mContext,
+ R.string.managed_profile_foreground_toast,
+ Toast.LENGTH_SHORT);
+ TextView text = (TextView) toast.getView().findViewById(
+ android.R.id.message);
+ text.setCompoundDrawablesRelativeWithIntrinsicBounds(
+ R.drawable.stat_sys_managed_profile_status, 0, 0, 0);
+ int paddingPx = mContext.getResources().getDimensionPixelSize(
+ R.dimen.managed_profile_toast_padding);
+ text.setCompoundDrawablePadding(paddingPx);
toast.show();
}
}
@@ -2098,4 +2101,11 @@
}
return mStatusBarKeyguardViewManager.isSecure();
}
+
+ @Override
+ public void showAssistDisclosure() {
+ if (mAssistManager != null) {
+ mAssistManager.showDisclosure();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 80fdd28..0deff08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -61,6 +61,7 @@
private static final int MSG_APP_TRANSITION_PENDING = 19 << MSG_SHIFT;
private static final int MSG_APP_TRANSITION_CANCELLED = 20 << MSG_SHIFT;
private static final int MSG_APP_TRANSITION_STARTING = 21 << MSG_SHIFT;
+ private static final int MSG_ASSIST_DISCLOSURE = 22 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -104,6 +105,7 @@
public void appTransitionPending();
public void appTransitionCancelled();
public void appTransitionStarting(long startTime, long duration);
+ public void showAssistDisclosure();
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -274,6 +276,13 @@
}
}
+ public void showAssistDisclosure() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_ASSIST_DISCLOSURE);
+ mHandler.obtainMessage(MSG_ASSIST_DISCLOSURE).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -366,6 +375,9 @@
Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
mCallbacks.appTransitionStarting(data.first, data.second);
break;
+ case MSG_ASSIST_DISCLOSURE:
+ mCallbacks.showAssistDisclosure();
+ break;
}
}
}
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 3737d05..a3bb129 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -26,6 +26,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
@@ -46,6 +47,7 @@
private ViewGroup mRoot;
private boolean mShowingSoon;
private Choreographer mChoreographer = Choreographer.getInstance();
+ private int mBouncerPromptReason;
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
@@ -68,6 +70,8 @@
return;
}
+ mBouncerPromptReason = mCallback.getBouncerPromptReason();
+
// Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
// Keyguard. If we need to authenticate, show the bouncer.
if (!mKeyguardView.dismiss()) {
@@ -84,12 +88,24 @@
public void run() {
mRoot.setVisibility(View.VISIBLE);
mKeyguardView.onResume();
+ showPromptReason(mBouncerPromptReason);
mKeyguardView.startAppearAnimation();
mShowingSoon = false;
mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
};
+ /**
+ * Show a string explaining why the security view needs to be solved.
+ *
+ * @param reason a flag indicating which string should be shown, see
+ * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+ * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
+ */
+ public void showPromptReason(int reason) {
+ mKeyguardView.showPromptReason(reason);
+ }
+
private void cancelShowRunnable() {
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null);
mShowingSoon = false;
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 cd90d27..ade40e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3101,16 +3101,16 @@
|| (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0;
}
- public void postStartSettingsActivity(final Intent intent, int delay) {
+ public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
- handleStartSettingsActivity(intent, true /*onlyProvisioned*/);
+ handleStartActivityDismissingKeyguard(intent, true /*onlyProvisioned*/);
}
}, delay);
}
- private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
+ private void handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) {
startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 25a93dd..12434ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -129,8 +129,8 @@
}
@Override
- public void startSettingsActivity(final Intent intent) {
- mStatusBar.postStartSettingsActivity(intent, 0);
+ public void startActivityDismissingKeyguard(final Intent intent) {
+ mStatusBar.postStartActivityDismissingKeyguard(intent, 0);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 3cc9297..daa84ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -154,6 +154,12 @@
}
private void updateConnected() {
+ // Make sure our connection state is up to date.
+ int state = mLocalBluetoothManager.getBluetoothAdapter().getConnectionState();
+ if (state != mConnectionState) {
+ mConnectionState = state;
+ mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
+ }
if (mLastDevice != null && mLastDevice.isConnected()) {
// Our current device is still valid.
return;
@@ -203,9 +209,9 @@
@Override
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
- mConnectionState = state;
mLastDevice = cachedDevice;
updateConnected();
+ mConnectionState = state;
mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 8dd087a..82b334a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -45,6 +45,7 @@
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -487,7 +488,7 @@
mLocalPowerManager.setDeviceIdleMode(true);
try {
mNetworkPolicyManager.setDeviceIdleMode(true);
- mBatteryStats.noteDeviceIdleMode(true, false, false);
+ mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
} catch (RemoteException e) {
}
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
@@ -496,18 +497,19 @@
mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
- mBatteryStats.noteDeviceIdleMode(false, false, false);
+ mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
} catch (RemoteException e) {
}
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
} break;
case MSG_REPORT_ACTIVE: {
- boolean fromMotion = msg.arg1 != 0;
+ String activeReason = (String)msg.obj;
+ int activeUid = msg.arg1;
boolean needBroadcast = msg.arg2 != 0;
mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
- mBatteryStats.noteDeviceIdleMode(false, !fromMotion, fromMotion);
+ mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
} catch (RemoteException e) {
}
if (needBroadcast) {
@@ -578,6 +580,12 @@
}
}
+ @Override public void exitIdle(String reason) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ exitIdleInternal(reason);
+ }
+
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
DeviceIdleController.this.dump(fd, pw, args);
}
@@ -818,6 +826,12 @@
}
}
+ public void exitIdleInternal(String reason) {
+ synchronized (this) {
+ becomeActiveLocked(reason, Binder.getCallingUid());
+ }
+ }
+
void updateDisplayLocked() {
mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
// We consider any situation where the display is showing something to be it on,
@@ -830,7 +844,7 @@
becomeInactiveIfAppropriateLocked();
} else if (screenOn) {
mScreenOn = true;
- becomeActiveLocked("screen");
+ becomeActiveLocked("screen", Process.myUid());
}
}
@@ -841,21 +855,21 @@
becomeInactiveIfAppropriateLocked();
} else if (charging) {
mCharging = charging;
- becomeActiveLocked("charging");
+ becomeActiveLocked("charging", Process.myUid());
}
}
- void scheduleReportActiveLocked(boolean fromMotion) {
- Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, fromMotion ? 1 : 0,
- mState == STATE_IDLE ? 1 : 0);
+ void scheduleReportActiveLocked(String activeReason, int activeUid) {
+ Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
+ mState == STATE_IDLE ? 1 : 0, activeReason);
mHandler.sendMessage(msg);
}
- void becomeActiveLocked(String reason) {
- if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + reason);
+ void becomeActiveLocked(String activeReason, int activeUid) {
+ if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
if (mState != STATE_ACTIVE) {
- EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason);
- scheduleReportActiveLocked(false);
+ EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
+ scheduleReportActiveLocked(activeReason, activeUid);
mState = STATE_ACTIVE;
mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
mNextIdlePendingDelay = 0;
@@ -896,7 +910,7 @@
if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
// Whoops, there is an upcoming alarm. We don't actually want to go idle.
if (mState != STATE_ACTIVE) {
- becomeActiveLocked("alarm");
+ becomeActiveLocked("alarm", Process.myUid());
}
return;
}
@@ -954,7 +968,7 @@
// state to wait again for no motion. Note that we only monitor for significant
// motion after moving out of the inactive state, so no need to worry about that.
if (mState != STATE_ACTIVE) {
- scheduleReportActiveLocked(true);
+ scheduleReportActiveLocked("motion", Process.myUid());
mState = STATE_ACTIVE;
mInactiveTimeout = mConstants.MOTION_INACTIVE_TIMEOUT;
EventLogTags.writeDeviceIdle(mState, "motion");
@@ -1240,7 +1254,7 @@
synchronized (this) {
if (!mIdleDisabled) {
mIdleDisabled = true;
- becomeActiveLocked("disabled");
+ becomeActiveLocked("disabled", Process.myUid());
pw.println("Idle mode disabled");
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 27983e2..1134556c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2488,10 +2488,7 @@
synchronized(bstats) {
synchronized(mPidsSelfLocked) {
if (haveNewCpuStats) {
- final int perc = bstats.startAddingCpuLocked();
- if (perc >= 0) {
- int remainUTime = 0;
- int remainSTime = 0;
+ if (bstats.startAddingCpuLocked()) {
int totalUTime = 0;
int totalSTime = 0;
final int N = mProcessCpuTracker.countStats();
@@ -2501,10 +2498,6 @@
continue;
}
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
- int otherUTime = (st.rel_utime*perc)/100;
- int otherSTime = (st.rel_stime*perc)/100;
- remainUTime += otherUTime;
- remainSTime += otherSTime;
totalUTime += st.rel_utime;
totalSTime += st.rel_stime;
if (pr != null) {
@@ -2513,8 +2506,7 @@
pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
pr.info.uid, pr.processName);
}
- ps.addCpuTimeLocked(st.rel_utime - otherUTime,
- st.rel_stime - otherSTime);
+ ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
pr.curCpuTime += st.rel_utime + st.rel_stime;
} else {
BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
@@ -2522,8 +2514,7 @@
st.batteryStats = ps = bstats.getProcessStatsLocked(
bstats.mapUid(st.uid), st.name);
}
- ps.addCpuTimeLocked(st.rel_utime - otherUTime,
- st.rel_stime - otherSTime);
+ ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
}
}
final int userTime = mProcessCpuTracker.getLastUserTime();
@@ -2532,9 +2523,8 @@
final int irqTime = mProcessCpuTracker.getLastIrqTime();
final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
final int idleTime = mProcessCpuTracker.getLastIdleTime();
- bstats.finishAddingCpuLocked(perc, remainUTime,
- remainSTime, totalUTime, totalSTime, userTime, systemTime,
- iowaitTime, irqTime, softIrqTime, idleTime);
+ bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime,
+ systemTime, iowaitTime, irqTime, softIrqTime, idleTime);
}
}
}
@@ -3274,9 +3264,9 @@
debugFlags |= Zygote.DEBUG_ENABLE_JIT;
}
}
- String genCFIDebugProperty = SystemProperties.get("debug.gencfi");
- if ("true".equals(genCFIDebugProperty)) {
- debugFlags |= Zygote.DEBUG_GENERATE_CFI;
+ String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
+ if ("true".equals(genDebugInfoProperty)) {
+ debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
}
if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
@@ -8280,7 +8270,7 @@
try {
if (AppGlobals.getPackageManager().isUidPrivileged(callingUid)) {
allowed = true;
- Slog.w(TAG, caller + ": caller " + callingUid
+ if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
+ " is using old GET_TASKS but privileged; allowing");
}
} catch (RemoteException e) {
@@ -8288,7 +8278,7 @@
}
}
if (!allowed) {
- Slog.w(TAG, caller + ": caller " + callingUid
+ if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
+ " does not hold REAL_GET_TASKS; limiting output");
}
return allowed;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9e33f2a..4e98576 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1915,7 +1915,12 @@
ActivityRecord intentActivity = !launchSingleInstance ?
findTaskLocked(r) : findActivityLocked(intent, r.info);
if (intentActivity != null) {
- if (isLockTaskModeViolation(intentActivity.task)) {
+ // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused
+ // but still needs to be a lock task mode violation since the task gets
+ // cleared out and the device would otherwise leave the locked task.
+ if (isLockTaskModeViolation(intentActivity.task,
+ (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
+ == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
@@ -3780,7 +3785,11 @@
}
boolean isLockTaskModeViolation(TaskRecord task) {
- if (getLockedTaskLocked() == task) {
+ return isLockTaskModeViolation(task, false);
+ }
+
+ boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
+ if (getLockedTaskLocked() == task && !isNewClearTask) {
return false;
}
final int lockTaskAuth = task.mLockTaskAuth;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c973386..3854e51 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -42,6 +42,7 @@
import android.telephony.TelephonyManager;
import android.util.Slog;
+import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsHelper;
@@ -64,16 +65,22 @@
implements PowerManagerInternal.LowPowerModeListener {
static final String TAG = "BatteryStatsService";
- private boolean mFirstExternalStatsUpdate = true;
static IBatteryStats sService;
final BatteryStatsImpl mStats;
final BatteryStatsHandler mHandler;
Context mContext;
PowerManagerInternal mPowerManagerInternal;
+ final int UPDATE_CPU = 0x01;
+ final int UPDATE_WIFI = 0x02;
+ final int UPDATE_RADIO = 0x04;
+ final int UPDATE_BT = 0x08;
+ final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
+
class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
public static final int MSG_SYNC_EXTERNAL_STATS = 1;
public static final int MSG_WRITE_TO_DISK = 2;
+ private int mUpdateFlags = 0;
public BatteryStatsHandler(Looper looper) {
super(looper);
@@ -83,11 +90,17 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SYNC_EXTERNAL_STATS:
- updateExternalStats((String)msg.obj, false);
+ final int updateFlags;
+ synchronized (this) {
+ removeMessages(MSG_SYNC_EXTERNAL_STATS);
+ updateFlags = mUpdateFlags;
+ mUpdateFlags = 0;
+ }
+ updateExternalStats((String)msg.obj, updateFlags);
break;
case MSG_WRITE_TO_DISK:
- updateExternalStats("write", true);
+ updateExternalStats("write", UPDATE_ALL);
synchronized (mStats) {
mStats.writeAsyncLocked();
}
@@ -97,9 +110,20 @@
@Override
public void scheduleSync(String reason) {
- if (!hasMessages(MSG_SYNC_EXTERNAL_STATS)) {
- Message msg = Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason);
- sendMessage(msg);
+ scheduleSyncImpl(reason, UPDATE_ALL);
+ }
+
+ @Override
+ public void scheduleWifiSync(String reason) {
+ scheduleSyncImpl(reason, UPDATE_WIFI);
+ }
+
+ private void scheduleSyncImpl(String reason, int updateFlags) {
+ synchronized (this) {
+ if (mUpdateFlags == 0) {
+ sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason));
+ }
+ mUpdateFlags |= updateFlags;
}
}
}
@@ -137,7 +161,7 @@
public void shutdown() {
Slog.w("BatteryStats", "Writing battery stats before shutdown...");
- updateExternalStats("shutdown", true);
+ updateExternalStats("shutdown", UPDATE_ALL);
synchronized (mStats) {
mStats.shutdownLocked();
}
@@ -237,7 +261,7 @@
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
- updateExternalStats("get-stats", true);
+ updateExternalStats("get-stats", UPDATE_ALL);
synchronized (mStats) {
mStats.writeToParcel(out, 0);
}
@@ -252,7 +276,7 @@
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
- updateExternalStats("get-stats", true);
+ updateExternalStats("get-stats", UPDATE_ALL);
synchronized (mStats) {
mStats.writeToParcel(out, 0);
}
@@ -603,8 +627,10 @@
// There was a change in WiFi power state.
// Collect data now for the past activity.
- mHandler.scheduleSync("wifi-data");
synchronized (mStats) {
+ if (mStats.isOnBattery()) {
+ mHandler.scheduleWifiSync("wifi-data");
+ }
mStats.noteWifiRadioPowerState(powerState, tsNanos);
}
}
@@ -767,10 +793,10 @@
}
@Override
- public void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion) {
+ public void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteDeviceIdleModeLocked(enabled, fromActive, fromMotion);
+ mStats.noteDeviceIdleModeLocked(enabled, activeReason, activeUid);
}
}
@@ -807,7 +833,7 @@
// Sync external stats first as the battery has changed states. If we don't sync
// immediately here, we may not collect the relevant data later.
- updateExternalStats("battery-state", false);
+ updateExternalStats("battery-state", UPDATE_ALL);
synchronized (mStats) {
mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
}
@@ -961,9 +987,9 @@
pw.println("Battery stats reset.");
noOutput = true;
}
- updateExternalStats("dump", true);
+ updateExternalStats("dump", UPDATE_ALL);
} else if ("--write".equals(arg)) {
- updateExternalStats("dump", true);
+ updateExternalStats("dump", UPDATE_ALL);
synchronized (mStats) {
mStats.writeSyncLocked();
pw.println("Battery stats written.");
@@ -1027,7 +1053,7 @@
flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
}
// Fetch data from external sources and update the BatteryStatsImpl object with them.
- updateExternalStats("dump", true);
+ updateExternalStats("dump", UPDATE_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1119,6 +1145,12 @@
return null;
}
+ final long timePeriodMs = info.mTimestamp - mLastInfo.mTimestamp;
+ final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
+ final long lastTxMs = mLastInfo.mControllerTxTimeMs;
+ final long lastRxMs = mLastInfo.mControllerRxTimeMs;
+ final long lastEnergy = mLastInfo.mControllerEnergyUsed;
+
// We will modify the last info object to be the delta, and store the new
// WifiActivityEnergyInfo object as our last one.
final WifiActivityEnergyInfo result = mLastInfo;
@@ -1126,19 +1158,16 @@
result.mStackState = info.getStackState();
// These times seem to be the most reliable.
- result.mControllerTxTimeMs =
- info.mControllerTxTimeMs - mLastInfo.mControllerTxTimeMs;
- result.mControllerRxTimeMs =
- info.mControllerRxTimeMs - mLastInfo.mControllerRxTimeMs;
+ result.mControllerTxTimeMs = info.mControllerTxTimeMs - lastTxMs;
+ result.mControllerRxTimeMs = info.mControllerRxTimeMs - lastRxMs;
// WiFi calculates the idle time as a difference from the on time and the various
// Rx + Tx times. There seems to be some missing time there because this sometimes
// becomes negative. Just cap it at 0 and move on.
// b/21613534
- result.mControllerIdleTimeMs =
- Math.max(0, info.mControllerIdleTimeMs - mLastInfo.mControllerIdleTimeMs);
+ result.mControllerIdleTimeMs = Math.max(0, info.mControllerIdleTimeMs - lastIdleMs);
result.mControllerEnergyUsed =
- Math.max(0, info.mControllerEnergyUsed - mLastInfo.mControllerEnergyUsed);
+ Math.max(0, info.mControllerEnergyUsed - lastEnergy);
if (result.mControllerTxTimeMs < 0 ||
result.mControllerRxTimeMs < 0) {
@@ -1151,6 +1180,34 @@
Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result);
}
+
+ final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs +
+ result.mControllerTxTimeMs;
+ if (totalTimeMs > timePeriodMs) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Total time ");
+ TimeUtils.formatDuration(totalTimeMs, sb);
+ sb.append(" is longer than sample period ");
+ TimeUtils.formatDuration(timePeriodMs, sb);
+ sb.append(".\n");
+ sb.append("Previous WiFi snapshot: ").append("idle=");
+ TimeUtils.formatDuration(lastIdleMs, sb);
+ sb.append(" rx=");
+ TimeUtils.formatDuration(lastRxMs, sb);
+ sb.append(" tx=");
+ TimeUtils.formatDuration(lastTxMs, sb);
+ sb.append(" e=").append(lastEnergy);
+ sb.append("\n");
+ sb.append("Current WiFi snapshot: ").append("idle=");
+ TimeUtils.formatDuration(info.mControllerIdleTimeMs, sb);
+ sb.append(" rx=");
+ TimeUtils.formatDuration(info.mControllerRxTimeMs, sb);
+ sb.append(" tx=");
+ TimeUtils.formatDuration(info.mControllerTxTimeMs, sb);
+ sb.append(" e=").append(info.mControllerEnergyUsed);
+ Slog.wtf(TAG, sb.toString());
+ }
+
mLastInfo = info;
return result;
}
@@ -1184,15 +1241,12 @@
* We first grab a lock specific to this method, then once all the data has been collected,
* we grab the mStats lock and update the data.
*
- * TODO(adamlesinski): When we start distributing bluetooth data to apps, we'll want to
- * separate these external stats so that they can be collected individually and on different
- * intervals.
- *
* @param reason The reason why this collection was requested. Useful for debugging.
- * @param force If false, some stats may decide not to be collected for efficiency as their
- * results aren't needed immediately. When true, collect all stats unconditionally.
+ * @param updateFlags Which external stats to update. Can be a combination of
+ * {@link #UPDATE_CPU}, {@link #UPDATE_RADIO}, {@link #UPDATE_WIFI},
+ * and {@link #UPDATE_BT}.
*/
- void updateExternalStats(String reason, boolean force) {
+ void updateExternalStats(final String reason, final int updateFlags) {
synchronized (mExternalStatsLock) {
if (mContext == null) {
// We haven't started yet (which means the BatteryStatsImpl object has
@@ -1200,34 +1254,46 @@
return;
}
- final WifiActivityEnergyInfo wifiEnergyInfo = pullWifiEnergyInfoLocked();
- final BluetoothActivityEnergyInfo bluetoothEnergyInfo;
- if (force) {
+ if (BatteryStatsImpl.DEBUG_ENERGY) {
+ Slog.d(TAG, "Updating external stats: reason=" + reason);
+ }
+
+ WifiActivityEnergyInfo wifiEnergyInfo = null;
+ if ((updateFlags & UPDATE_WIFI) != 0) {
+ wifiEnergyInfo = pullWifiEnergyInfoLocked();
+ }
+
+ BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
+ if ((updateFlags & UPDATE_BT) != 0) {
// We only pull bluetooth stats when we have to, as we are not distributing its
// use amongst apps and the sampling frequency does not matter.
bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
- } else {
- bluetoothEnergyInfo = null;
}
synchronized (mStats) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
if (mStats.mRecordAllHistory) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
mStats.addHistoryEventLocked(elapsedRealtime, uptime,
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0);
}
- mStats.updateCpuTimeLocked(mFirstExternalStatsUpdate);
- mStats.updateKernelWakelocksLocked();
- mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime());
- mStats.updateWifiStateLocked(wifiEnergyInfo);
- mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
- }
- if (mFirstExternalStatsUpdate) {
- // We have read the stats for the first time, which means we have a baseline
- // from which to calculate delta.
- mFirstExternalStatsUpdate = false;
+ if ((updateFlags & UPDATE_CPU) != 0) {
+ mStats.updateCpuTimeLocked();
+ mStats.updateKernelWakelocksLocked();
+ }
+
+ if ((updateFlags & UPDATE_RADIO) != 0) {
+ mStats.updateMobileRadioStateLocked(elapsedRealtime);
+ }
+
+ if ((updateFlags & UPDATE_WIFI) != 0) {
+ mStats.updateWifiStateLocked(wifiEnergyInfo);
+ }
+
+ if ((updateFlags & UPDATE_BT) != 0) {
+ mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 4ccb5ad..f72b598 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -46,10 +46,12 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.speech.RecognizerIntent;
@@ -1086,6 +1088,14 @@
voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH");
} else {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
+ }
voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE,
isLocked && mKeyguardManager.isKeyguardSecure());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6de81df..e7fddb9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8253,6 +8253,7 @@
} else {
res.icon = info.icon;
}
+ res.iconResourceId = info.icon;
res.system = res.activityInfo.applicationInfo.isSystemApp();
return res;
}
@@ -12499,6 +12500,8 @@
if (clearPackagePreferredActivitiesLPw(packageName, removeUser)) {
scheduleWritePackageRestrictionsLocked(removeUser);
}
+ revokeRuntimePermissionsAndClearAllFlagsLocked(ps.getPermissionsState(),
+ removeUser);
}
return true;
}
@@ -12705,13 +12708,37 @@
| PackageManager.FLAG_PERMISSION_USER_FIXED
| PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId, userSetFlags);
+ }
+
+ /**
+ * Revokes granted runtime permissions and clears all flags.
+ *
+ * @param permissionsState The permission state to reset.
+ * @param userId The device user for which to do a reset.
+ */
+ private void revokeRuntimePermissionsAndClearAllFlagsLocked(
+ PermissionsState permissionsState, int userId) {
+ revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId,
+ PackageManager.MASK_PERMISSION_FLAGS);
+ }
+
+ /**
+ * Revokes granted runtime permissions and clears certain flags.
+ *
+ * @param permissionsState The permission state to reset.
+ * @param userId The device user for which to do a reset.
+ * @param flags The flags that is going to be reset.
+ */
+ private void revokeRuntimePermissionsAndClearFlagsLocked(
+ PermissionsState permissionsState, int userId, int flags) {
boolean needsWrite = false;
for (PermissionState state : permissionsState.getRuntimePermissionStates(userId)) {
BasePermission bp = mSettings.mPermissions.get(state.getName());
if (bp != null) {
permissionsState.revokeRuntimePermission(bp, userId);
- permissionsState.updatePermissionFlags(bp, userId, userSetFlags, 0);
+ permissionsState.updatePermissionFlags(bp, userId, flags, 0);
needsWrite = true;
}
}
@@ -14090,7 +14117,9 @@
}
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)
+ && packageName == null) {
pw.println();
int count = mSettings.mPackages.size();
if (count == 0) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index cd50946..4b36581 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2098,7 +2098,7 @@
}
final ApplicationInfo ai = pkg.pkg.applicationInfo;
- final String dataPath = ai.dataDir;
+ final String dataPath = new File(ai.dataDir).getCanonicalPath();
final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
final int[] gids = pkg.getPermissionsState().computeGids(userIds);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6fb9a5c..bd545df 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -56,6 +56,7 @@
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
@@ -2734,6 +2735,14 @@
if (!keyguardOn) {
voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
} else {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
+ }
voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
}
@@ -5192,6 +5201,14 @@
}
void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
+ }
Intent voiceIntent =
new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 58c3ea1..4692403 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -24,4 +24,5 @@
void notificationLightPulse(int argb, int onMillis, int offMillis);
void notificationLightOff();
void showScreenPinningRequest();
+ void showAssistDisclosure();
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 5669f30..a754379 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -154,6 +154,16 @@
}
}
}
+
+ @Override
+ public void showAssistDisclosure() {
+ if (mBar != null) {
+ try {
+ mBar.showAssistDisclosure();
+ } catch (RemoteException e) {
+ }
+ }
+ }
};
// ================================================================================
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index ac79b36..d4c5f87 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -40,8 +40,6 @@
private boolean mRelroReady32Bit = false;
private boolean mRelroReady64Bit = false;
- private String oldWebViewPackageName = null;
-
private BroadcastReceiver mWebViewUpdatedReceiver;
public WebViewUpdateService(Context context) {
@@ -53,22 +51,9 @@
mWebViewUpdatedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
-
- for (String packageName : WebViewFactory.getWebViewPackageNames()) {
- String webviewPackage = "package:" + packageName;
-
- if (webviewPackage.equals(intent.getDataString())) {
- String usedPackageName =
- WebViewFactory.findPreferredWebViewPackage().packageName;
- // Only trigger update actions if the updated package is the one that
- // will be used, or the one that was in use before the update.
- if (packageName.equals(usedPackageName) ||
- packageName.equals(oldWebViewPackageName)) {
- onWebViewUpdateInstalled();
- oldWebViewPackageName = usedPackageName;
- }
- return;
- }
+ String webviewPackage = "package:" + WebViewFactory.getWebViewPackageName();
+ if (webviewPackage.equals(intent.getDataString())) {
+ onWebViewUpdateInstalled();
}
}
};
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index acd484d..af0ddbe 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -139,7 +139,7 @@
IVoiceInteractionSessionShowCallback showCallback) {
if (mActiveSession == null) {
mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName,
- mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid);
+ mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler);
}
return mActiveSession.showLocked(args, flags, showCallback);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 47a230a..cc6a9c5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -32,6 +32,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -48,6 +49,8 @@
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
+import com.android.server.LocalServices;
+import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -63,6 +66,7 @@
final Context mContext;
final Callback mCallback;
final int mCallingUid;
+ final Handler mHandler;
final IActivityManager mAm;
final IWindowManager mIWindowManager;
final AppOpsManager mAppOps;
@@ -141,13 +145,14 @@
};
public VoiceInteractionSessionConnection(Object lock, ComponentName component, int user,
- Context context, Callback callback, int callingUid) {
+ Context context, Callback callback, int callingUid, Handler handler) {
mLock = lock;
mSessionComponentName = component;
mUser = user;
mContext = context;
mCallback = callback;
mCallingUid = callingUid;
+ mHandler = handler;
mAm = ActivityManagerNative.getDefault();
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -193,11 +198,13 @@
mShowArgs = args;
mShowFlags = flags;
mHaveAssistData = false;
+ boolean needDisclosure = false;
if ((flags& VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
&& allDataEnabled) {
try {
+ needDisclosure = true;
mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
mAssistReceiver);
} catch (RemoteException e) {
@@ -215,6 +222,7 @@
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
&& allDataEnabled) {
try {
+ needDisclosure = true;
mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
} catch (RemoteException e) {
}
@@ -225,6 +233,9 @@
} else {
mScreenshot = null;
}
+ if (needDisclosure) {
+ mHandler.post(mShowAssistDisclosureRunnable);
+ }
if (mSession != null) {
try {
mSession.show(mShowArgs, mShowFlags, showCallback);
@@ -483,4 +494,15 @@
pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData);
}
}
+
+ private Runnable mShowAssistDisclosureRunnable = new Runnable() {
+ @Override
+ public void run() {
+ StatusBarManagerInternal statusBarInternal = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ if (statusBarInternal != null) {
+ statusBarInternal.showAssistDisclosure();
+ }
+ }
+ };
};
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0eb94b8..01cab33 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -249,32 +249,24 @@
/* The following 3 fields are related to carrier visual voicemail. */
/**
- * The carrier number MO sms messages are sent to.
- *
- * @hide
+ * The carrier number mobile outgoing (MO) sms messages are sent to.
*/
public static final String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
/**
- * The port through which the MO sms messages are sent through.
- *
- * @hide
+ * The port through which the mobile outgoing (MO) sms messages are sent through.
*/
public static final String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
/**
* The type of visual voicemail protocol the carrier adheres to. See {@link TelephonyManager}
* for possible values. For example {@link TelephonyManager#VVM_TYPE_OMTP}.
- *
- * @hide
*/
public static final String KEY_VVM_TYPE_STRING = "vvm_type_string";
/**
* The package name of the carrier's visual voicemail app to ensure that dialer visual voicemail
* and carrier visual voicemail are not active at the same time.
- *
- * @hide
*/
public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c6fadda..f77d268 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -616,15 +616,11 @@
/**
* The OMTP protocol.
- *
- * @hide
*/
public static final String VVM_TYPE_OMTP = "vvm_type_omtp";
/**
- * A flavor of OMTP protocol for Comverse.
- *
- * @hide
+ * A flavor of OMTP protocol with a different mobile originated (MO) format
*/
public static final String VVM_TYPE_CVVM = "vvm_type_cvvm";