diff options
89 files changed, 1523 insertions, 570 deletions
diff --git a/api/current.txt b/api/current.txt index 7891c710381b..a0dccd5963a1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15863,6 +15863,10 @@ package android.media {      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 @@ package android.telephony {      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 @@ package android.telephony {      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 @@ package android.telephony {      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 @@ package android.view {      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 aa6f8280e821..7e3e051e6a4a 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -17118,6 +17118,10 @@ package android.media {      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 @@ package android.telephony {      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 @@ package android.telephony {      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 @@ package android.telephony {      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 @@ package android.view {      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 146138007138..e17808744408 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -35,6 +35,9 @@ import android.os.RemoteException;  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 @@ class ApplicationThreadProxy implements IApplicationThread {          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 08c52365c750..d83dfc5eb54f 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -1480,7 +1480,11 @@ public class IntentFilter implements Parcelable {       * 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 649fdb46367e..7bab35ce7e8e 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -45,7 +45,7 @@ public class ResolveInfo implements Parcelable {       * {@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 @@ public class ResolveInfo implements Parcelable {       * 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 @@ public class ResolveInfo implements Parcelable {       * 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 @@ public class ResolveInfo implements Parcelable {       * 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 class ResolveInfo implements Parcelable {      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 @@ public class ResolveInfo implements Parcelable {       * 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 @@ public class ResolveInfo implements Parcelable {          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 @@ public class ResolveInfo implements Parcelable {       * @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 @@ public class ResolveInfo implements Parcelable {          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 @@ public class ResolveInfo implements Parcelable {          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 @@ public class ResolveInfo implements Parcelable {          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 f8db6d9e3010..c656fb8b8352 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -667,7 +667,7 @@ public abstract class CameraMetadata<TKey> {       * {@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 @@ public abstract class CameraMetadata<TKey> {       * <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 abstract class CameraMetadata<TKey> {       */      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 bc625dd31168..9fa66879629d 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -1448,9 +1448,9 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>       * <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 da216aaa4418..b1fb615821c7 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -1960,9 +1960,9 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * <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 d165240e2394..eb6e1c2f4a87 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1165,25 +1165,23 @@ public abstract class BatteryStats implements Parcelable {          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 abstract class BatteryStats implements Parcelable {      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 @@ public abstract class BatteryStats implements Parcelable {              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 268295dc40c0..fe4aa13fe968 100644 --- a/core/java/android/os/IDeviceIdleController.aidl +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -28,4 +28,5 @@ interface IDeviceIdleController {      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 dbb51464cb87..f9c50f320dbb 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -635,8 +635,8 @@ public class Process {              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 3fb93c4be250..62c28ac14255 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -81,8 +81,8 @@ public final class KeymasterDefs {      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 final class KeymasterDefs {      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 8c6cd09a8144..0309d24c8e56 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -41,6 +41,7 @@ import android.util.ArrayMap;  import android.util.ArraySet;  import android.util.Log; +import java.util.ArrayList;  import java.util.Collections;  import java.util.List; @@ -463,15 +464,28 @@ public abstract class NotificationListenerService extends Service {              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 @@ public abstract class NotificationListenerService extends Service {                  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 80dcecce8bc2..ea979c8b4621 100644 --- a/core/java/android/view/ActionMode.java +++ b/core/java/android/view/ActionMode.java @@ -261,6 +261,16 @@ public abstract class ActionMode {      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 2f5c9e2d2d45..7db88af5f71e 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -298,14 +298,27 @@ public class WebViewClient {       * 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 b4ef58afb94d..3b9aca8883e3 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -96,49 +96,27 @@ public final class WebViewFactory {          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 @@ public final class WebViewFactory {      /**       * 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 @@ public final class WebViewFactory {      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 @@ public final class WebViewFactory {          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 a15080e60331..ebb54ff39d06 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.os.SystemClock;  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 @@ public class Chronometer extends TextView {      }      private long mBase; +    private long mNow; // the currently displayed time      private boolean mVisible;      private boolean mStarted;      private boolean mRunning; @@ -224,6 +227,7 @@ public class Chronometer extends TextView {      }      private synchronized void updateText(long now) { +        mNow = now;          long seconds = now - mBase;          seconds /= 1000;          String text = DateUtils.formatElapsedTime(mRecycle, seconds); @@ -279,6 +283,60 @@ public class Chronometer extends TextView {          }      } +    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 339038eddf3f..affc5daa35f7 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -522,7 +522,7 @@ public class RelativeLayout extends ViewGroup {          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 @@ public class RelativeLayout extends ViewGroup {              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 @@ public class RelativeLayout extends ViewGroup {              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 @@ public class RelativeLayout extends ViewGroup {              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 @@ public class RelativeLayout extends ViewGroup {          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 c1ec6e6907cd..2a13c7646eac 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -613,15 +613,17 @@ public class ChooserActivity extends ResolverActivity {                      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 929cacd553f6..6f0cec60bd46 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -116,7 +116,7 @@ interface IBatteryStats {      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 39c86f99c55b..e14f0584a0b8 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -1186,15 +1186,17 @@ public class ResolverActivity extends Activity {                          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 07d1fc8624de..229079f728d0 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -95,7 +95,8 @@ import java.util.concurrent.locks.ReentrantLock;  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 @@ public final class BatteryStatsImpl extends BatteryStats {      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 @@ public final class BatteryStatsImpl extends BatteryStats {              BatteryCallback cb = mCallback;              switch (msg.what) {                  case MSG_UPDATE_WAKELOCKS: +                    synchronized (BatteryStatsImpl.this) { +                        updateCpuTimeLocked(); +                    }                      if (cb != null) {                          cb.batteryNeedsCpuUpdate();                      } @@ -178,6 +182,7 @@ public final class BatteryStatsImpl extends BatteryStats {      public interface ExternalStatsSync {          void scheduleSync(String reason); +        void scheduleWifiSync(String reason);      }      public final MyHandler mHandler; @@ -2503,12 +2508,11 @@ public final class BatteryStatsImpl extends BatteryStats {          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 @@ public final class BatteryStatsImpl extends BatteryStats {              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 @@ public final class BatteryStatsImpl extends BatteryStats {              }          }          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 @@ public final class BatteryStatsImpl extends BatteryStats {          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 @@ public final class BatteryStatsImpl extends BatteryStats {          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 final class BatteryStatsImpl extends BatteryStats {          }      } -    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 @@ public final class BatteryStatsImpl extends BatteryStats {          }          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 @@ public final class BatteryStatsImpl extends BatteryStats {              addHistoryRecordLocked(elapsedRealtime, uptime);              mWifiOn = true;              mWifiOnTimer.startRunningLocked(elapsedRealtime); -            scheduleSyncExternalStatsLocked("wifi-off"); +            scheduleSyncExternalWifiStatsLocked("wifi-off");          }      } @@ -3594,7 +3505,7 @@ public final class BatteryStatsImpl extends BatteryStats {              addHistoryRecordLocked(elapsedRealtime, uptime);              mWifiOn = false;              mWifiOnTimer.stopRunningLocked(elapsedRealtime); -            scheduleSyncExternalStatsLocked("wifi-on"); +            scheduleSyncExternalWifiStatsLocked("wifi-on");          }      } @@ -3846,7 +3757,7 @@ public final class BatteryStatsImpl extends BatteryStats {                  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 @@ public final class BatteryStatsImpl extends BatteryStats {                  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 @@ public final class BatteryStatsImpl extends BatteryStats {              }              mWifiState = wifiState;              mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime); -            scheduleSyncExternalStatsLocked("wifi-state"); +            scheduleSyncExternalWifiStatsLocked("wifi-state");          }      } @@ -7632,6 +7543,10 @@ public final class BatteryStatsImpl extends BatteryStats {       * @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 @@ public final class BatteryStatsImpl extends BatteryStats {       * 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 @@ public final class BatteryStatsImpl extends BatteryStats {       * @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 @@ public final class BatteryStatsImpl extends BatteryStats {          }      } +    // 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); + +        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++; +                } +            } +        } + +        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]);                          } -                        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); +            }          } -        mKernelUidCpuTimeReader.readDelta(callback);      }      boolean setChargingLocked(boolean charging) { @@ -8157,6 +8246,12 @@ public final class BatteryStatsImpl extends BatteryStats {          }      } +    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 b2363786029c..62926d170632 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 @@ public class KernelUidCpuTimeReader {      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 @@ public class KernelUidCpuTimeReader {       *                 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 @@ public class KernelUidCpuTimeReader {                          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 @@ public class KernelUidCpuTimeReader {          } 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 4f6d78187578..c97fdf46cda9 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -41,8 +41,8 @@ public final class Zygote {      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 1a0345bcac04..fa870b9ddedf 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -322,7 +322,7 @@ class ZygoteConnection {          /**           * 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 @@ class ZygoteConnection {                      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 66f6079b47e9..15ed5bd0b539 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -3223,12 +3223,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {                  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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {              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 9f99f6235787..0732addb7356 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -64,5 +64,7 @@ oneway interface IStatusBar       *        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 62e724aba553..9d0636a744d8 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -387,4 +387,26 @@ public class ArrayUtils {      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 784b256728ca..863506b0a63a 100644 --- a/core/java/com/android/internal/view/FloatingActionMode.java +++ b/core/java/com/android/internal/view/FloatingActionMode.java @@ -197,6 +197,13 @@ public class FloatingActionMode extends ActionMode {      }      @Override +    public void onWindowFocusChanged(boolean hasWindowFocus) { +        checkToolbarInitialized(); +        mFloatingToolbarVisibilityHelper.setWindowFocused(hasWindowFocus); +        mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); +    } + +    @Override      public void finish() {          checkToolbarInitialized();          reset(); @@ -237,6 +244,7 @@ public class FloatingActionMode extends ActionMode {      }      private void reset() { +        mFloatingToolbar.dismiss();          mFloatingToolbarVisibilityHelper.deactivate();          mOriginatingView.removeCallbacks(mMovingOff);          mOriginatingView.removeCallbacks(mHideOff); @@ -253,6 +261,7 @@ public class FloatingActionMode extends ActionMode {          private boolean mHideRequested;          private boolean mMoving;          private boolean mOutOfBounds; +        private boolean mWindowFocused = true;          private boolean mActive; @@ -264,6 +273,7 @@ public class FloatingActionMode extends ActionMode {              mHideRequested = false;              mMoving = false;              mOutOfBounds = false; +            mWindowFocused = true;              mActive = true;          } @@ -285,12 +295,16 @@ public class FloatingActionMode extends ActionMode {              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 e19b2b60be5d..85ec29c4634c 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -409,8 +409,8 @@ public class IInputConnectionWrapper extends IInputContext.Stub {              }              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 65f2f53f8987..523663c0e6e4 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -546,25 +546,25 @@ public final class FloatingToolbar {          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 @@ public final class FloatingToolbar {                              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 @@ public final class FloatingToolbar {          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 7c2b28dcc2b1..2c35a8be98c2 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -876,16 +876,16 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)                         "-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 7272ae304384..424a0b7d219d 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 4160e0e5c3eb..295251c55718 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 9a8345067c5d..7b1169f8e34b 100644 --- a/docs/html/sdk/index.jd +++ b/docs/html/sdk/index.jd @@ -30,21 +30,22 @@ studio.win_notools_exe_checksum=ae09797db2537afb572a00b7eacc292bb66d539e -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 326fbe29fe6a..934b262b67a6 100644 --- a/docs/html/tools/sdk/tools-notes.jd +++ b/docs/html/tools/sdk/tools-notes.jd @@ -25,6 +25,36 @@ href="http://tools.android.com/knownissues">http://tools.android.com/knownissues  <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 9acfee2d2309..ab61e2bfcbd3 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -89,10 +89,23 @@ import android.util.Log;   * 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 000000000000..3b2da1e8bd25 --- /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 d456dc1080d2..9ec0312d0f2a 100644 --- a/media/jni/android_media_MediaDrm.cpp +++ b/media/jni/android_media_MediaDrm.cpp @@ -308,6 +308,10 @@ static bool throwExceptionAsNecessary(      } 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 fdc586b8a175..aba4bbeb1e70 100644 --- a/media/jni/audioeffect/android_media_AudioEffect.cpp +++ b/media/jni/audioeffect/android_media_AudioEffect.cpp @@ -472,6 +472,8 @@ static void android_media_AudioEffect_native_release(JNIEnv *env,  jobject thiz)      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 6098b4a47fa9..05570195752b 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -450,6 +450,8 @@ static void android_media_visualizer_native_release(JNIEnv *env,  jobject thiz)      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 aa99a7bfeb72..0c6837fcc60c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -216,6 +216,19 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout          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 cd4b24a9e178..ff4e8154d0f5 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -160,6 +160,17 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {      }      /** +     * 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 c9ad7286d9f6..2db87b330077 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java @@ -111,6 +111,16 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView      }      @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 1bd0bb4dcec5..59a8ad576ebb 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java @@ -85,10 +85,9 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit          }      };      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 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit          // 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 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit      }      @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 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit                      }                  },                  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 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit                          }                      }                  }, 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 23834a31923c..07947b182d46 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -93,6 +93,16 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView          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 d17b25a6a87c..f529ac0f3497 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -509,6 +509,13 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe      }      @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 5b5023602010..5658a7492d93 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java @@ -21,6 +21,9 @@ public interface KeyguardSecurityView {      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 @@ public interface KeyguardSecurityView {      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 54467f3863cf..a0ff21b1fd51 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java @@ -131,6 +131,14 @@ public class KeyguardSecurityViewFlipper extends ViewFlipper implements Keyguard      }      @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 f4acff8beb2b..aeac91215be6 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java @@ -95,6 +95,12 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {          }      } +    @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 b85d96608f2c..af882395ee79 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java @@ -140,6 +140,12 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {          }      } +    @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 273f166888e6..022338dab34c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -804,8 +804,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {      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 class KeyguardUpdateMonitor implements TrustManager.TrustListener {          }      } +    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 f5c809a61db1..ff463c6c8312 100644 --- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java @@ -81,4 +81,12 @@ public interface ViewMediatorCallback {       * @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 b0429ef43cf9..249eaa5d44d3 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 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe              // 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 13747ed99820..0c84fa148e7f 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.app.PendingIntent;  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 @@ public class BugreportReceiver extends BroadcastReceiver {      @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 @@ public class BugreportReceiver extends BroadcastReceiver {          }.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 5c77b9a1f660..000000000000 --- 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 5a01ca7f16a6..000000000000 --- 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 9a96939f700d..0dcbe884b30f 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 b0e71f916f20..869b03a8a7b5 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 000000000000..234a6992f49e --- /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 445ecb659a63..674356b0f866 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 @@ public class AssistManager {      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 @@ public class AssistManager {                  Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false,                  mAssistSettingsObserver);          mAssistSettingsObserver.onChange(false); +        mAssistDisclosure = new AssistDisclosure(context, new Handler());      }      public void onConfigurationChanged() { @@ -187,8 +190,11 @@ public class AssistManager {          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 @@ public class AssistManager {              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 @@ public class AssistManager {          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 c06b34fa1ffb..80761d80fa99 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.telephony.IccCardConstants;  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 class KeyguardViewMediator extends SystemUI {          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 9761cd19e195..4b1453d09ed8 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 @@ public class QSPanel extends ViewGroup {              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 72bb136bcc99..38fade21390f 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 abstract class QSTile<TState extends State> implements Listenable {      }      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 a9e8b383a8a0..07406b98f8be 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 @@ public class CellularTile extends QSTile<QSTile.SignalState> {          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 f97f519cafc2..1b74eb6cd3be 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 @@ public class DndTile extends QSTile<QSTile.BooleanState> {      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 19f4df6ba06c..f7f7acb8a072 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 @@ public class IntentTile extends QSTile<QSTile.State> {      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 9bc5b75632f7..c33ef7caeeab 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 @@ public class WifiTile extends QSTile<QSTile.SignalState> {      @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 @@ public class WifiTile extends QSTile<QSTile.SignalState> {          @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 a4965488e34d..295fdc81e775 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 @@ public abstract class BaseStatusBar extends SystemUI implements                  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 @@ public abstract class BaseStatusBar extends SystemUI implements          }          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 80fdd288781e..0deff08367f0 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 @@ public class CommandQueue extends IStatusBar.Stub {      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 class CommandQueue extends IStatusBar.Stub {          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 class CommandQueue extends IStatusBar.Stub {          }      } +    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 @@ public class CommandQueue extends IStatusBar.Stub {                      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 3737d0581761..a3bb1296dccd 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 android.view.accessibility.AccessibilityEvent;  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 @@ public class KeyguardBouncer {      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 @@ public class KeyguardBouncer {              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 class KeyguardBouncer {          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 cd90d2705acf..ade40e507173 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 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,                  || (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 25a93ddfd819..12434ac2af5b 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 @@ public class QSTileHost implements QSTile.Host, Tunable {      }      @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 3cc92978d393..daa84ad80ccf 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 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa      }      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 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa      @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 8dd087a135ff..82b334a3c25c 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.Looper;  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 @@ public class DeviceIdleController extends SystemService                      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 @@ public class DeviceIdleController extends SystemService                      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 @@ public class DeviceIdleController extends SystemService              }          } +        @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 class DeviceIdleController extends SystemService          }      } +    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 @@ public class DeviceIdleController extends SystemService              becomeInactiveIfAppropriateLocked();          } else if (screenOn) {              mScreenOn = true; -            becomeActiveLocked("screen"); +            becomeActiveLocked("screen", Process.myUid());          }      } @@ -841,21 +855,21 @@ public class DeviceIdleController extends SystemService              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 @@ public class DeviceIdleController extends SystemService          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 @@ public class DeviceIdleController extends SystemService          // 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 @@ public class DeviceIdleController extends SystemService                      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 27983e24734d..1134556cccc3 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 @@ public final class ActivityManagerService extends ActivityManagerNative              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 @@ public final class ActivityManagerService extends ActivityManagerNative                                      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 @@ public final class ActivityManagerService extends ActivityManagerNative                                          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 @@ public final class ActivityManagerService extends ActivityManagerNative                                          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 @@ public final class ActivityManagerService extends ActivityManagerNative                              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 @@ public final class ActivityManagerService extends ActivityManagerNative                      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 @@ public final class ActivityManagerService extends ActivityManagerNative                  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 @@ public final class ActivityManagerService extends ActivityManagerNative              }          }          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 9e33f2a99607..4e98576e6fb9 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 @@ public final class ActivityStackSupervisor implements DisplayListener {                  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 @@ public final class ActivityStackSupervisor implements DisplayListener {      }      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 c973386e4bb8..3854e5160fc6 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.SignalStrength;  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 @@ public final class BatteryStatsService extends IBatteryStats.Stub          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 final class BatteryStatsService extends IBatteryStats.Stub          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 @@ public final class BatteryStatsService extends IBatteryStats.Stub          @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 final class BatteryStatsService extends IBatteryStats.Stub      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 @@ public final class BatteryStatsService extends IBatteryStats.Stub          //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 @@ public final class BatteryStatsService extends IBatteryStats.Stub          //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 @@ public final class BatteryStatsService extends IBatteryStats.Stub          // 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 @@ public final class BatteryStatsService extends IBatteryStats.Stub      }      @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 @@ public final class BatteryStatsService extends IBatteryStats.Stub          // 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 @@ public final class BatteryStatsService extends IBatteryStats.Stub                          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 @@ public final class BatteryStatsService extends IBatteryStats.Stub                  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 @@ public final class BatteryStatsService extends IBatteryStats.Stub                      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 @@ public final class BatteryStatsService extends IBatteryStats.Stub                  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 @@ public final class BatteryStatsService extends IBatteryStats.Stub                      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 @@ public final class BatteryStatsService extends IBatteryStats.Stub       * 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 @@ public final class BatteryStatsService extends IBatteryStats.Stub                  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 4ccb5ad777d2..f72b5987d7ac 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.Binder;  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 @@ public class MediaFocusControl implements OnFinished {              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 6de81dfcdf3b..e7fddb96249e 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 @@ public class PackageManagerService extends IPackageManager.Stub {              } else {                  res.icon = info.icon;              } +            res.iconResourceId = info.icon;              res.system = res.activityInfo.applicationInfo.isSystemApp();              return res;          } @@ -12499,6 +12500,8 @@ public class PackageManagerService extends IPackageManager.Stub {                  if (clearPackagePreferredActivitiesLPw(packageName, removeUser)) {                      scheduleWritePackageRestrictionsLocked(removeUser);                  } +                revokeRuntimePermissionsAndClearAllFlagsLocked(ps.getPermissionsState(), +                        removeUser);              }              return true;          } @@ -12705,13 +12708,37 @@ public class PackageManagerService extends IPackageManager.Stub {                  | 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 @@ public class PackageManagerService extends IPackageManager.Stub {                  }              } -            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 cd50946567a7..4b36581df06f 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 class Settings {                  }                  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 6fb9a5cd040e..bd545dfaaa8a 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.Debug;  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 @@ public class PhoneWindowManager implements WindowManagerPolicy {                  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 @@ public class PhoneWindowManager implements WindowManagerPolicy {      }      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 58c3ea1f619c..469240349d64 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 @@ public interface StatusBarManagerInternal {      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 5669f30757d9..a7543790cc10 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 @@ public class StatusBarManagerService extends IStatusBarService.Stub {                  }              }          } + +        @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 ac79b36f7005..d4c5f8716c0e 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 @@ public class WebViewUpdateService extends SystemService {      private boolean mRelroReady32Bit = false;      private boolean mRelroReady64Bit = false; -    private String oldWebViewPackageName = null; -      private BroadcastReceiver mWebViewUpdatedReceiver;      public WebViewUpdateService(Context context) { @@ -53,22 +51,9 @@ public class WebViewUpdateService extends SystemService {          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 acd484dac0c8..af0ddbe82ca4 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 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne              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 47a230afb72a..cc6a9c52d8a5 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.graphics.Bitmap;  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.IAssistScreenshotReceiver;  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 class VoiceInteractionSessionConnection implements ServiceConnection {      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 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {      };      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 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {              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 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {                          mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED                          && allDataEnabled) {                      try { +                        needDisclosure = true;                          mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);                      } catch (RemoteException e) {                      } @@ -225,6 +233,9 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {              } else {                  mScreenshot = null;              } +            if (needDisclosure) { +                mHandler.post(mShowAssistDisclosureRunnable); +            }              if (mSession != null) {                  try {                      mSession.show(mShowArgs, mShowFlags, showCallback); @@ -483,4 +494,15 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {              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 0eb94b8c1e30..01cab339fe33 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -249,32 +249,24 @@ public class CarrierConfigManager {      /* 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 c6faddae7fbf..f77d268addd1 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -616,15 +616,11 @@ public class TelephonyManager {      /**       * 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";  |