diff options
52 files changed, 1385 insertions, 269 deletions
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index c88518e10513..f7d1b8df9284 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1258,7 +1258,9 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>If this device is the largest or only camera device with a given facing, then this * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm * from the main sensor along the +X axis (to the right from the user's perspective) will - * report <code>(0.03, 0, 0)</code>.</p> + * report <code>(0.03, 0, 0)</code>. Note that this means that, for many computer vision + * applications, the position needs to be negated to convert it to a translation from the + * camera to the origin.</p> * <p>To transform a pixel coordinates between two cameras facing the same direction, first * the source camera {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} must be corrected for. Then the source * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the @@ -1270,7 +1272,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>To compare this against a real image from the destination camera, the destination camera * image then needs to be corrected for radial distortion before comparison or sampling.</p> * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to - * the center of the primary gyroscope on the device.</p> + * the center of the primary gyroscope on the device. The axis definitions are the same as + * with PRIMARY_CAMERA.</p> * <p><b>Units</b>: Meters</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * @@ -1302,13 +1305,15 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * </code></pre> * <p>which can then be combined with the camera pose rotation * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and - * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the + * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respectively) to calculate the * complete transform from world coordinates to pixel * coordinates:</p> - * <pre><code>P = [ K 0 * [ R t - * 0 1 ] 0 1 ] + * <pre><code>P = [ K 0 * [ R -Rt + * 0 1 ] 0 1 ] * </code></pre> - * <p>and with <code>p_w</code> being a point in the world coordinate system + * <p>(Note the negation of poseTranslation when mapping from camera + * to world coordinates, and multiplication by the rotation).</p> + * <p>With <code>p_w</code> being a point in the world coordinate system * and <code>p_s</code> being a point in the camera active pixel array * coordinate system, and with the mapping including the * homogeneous division by z:</p> @@ -1330,6 +1335,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * activeArraySize rectangle), to determine the final pixel * coordinate of the world point for processed (non-RAW) * output buffers.</p> + * <p>For camera devices, the center of pixel <code>(x,y)</code> is located at + * coordinate <code>(x + 0.5, y + 0.5)</code>. So on a device with a + * precorrection active array of size <code>(10,10)</code>, the valid pixel + * indices go from <code>(0,0)-(9,9)</code>, and an perfectly-built camera would + * have an optical center at the exact center of the pixel grid, at + * coordinates <code>(5.0, 5.0)</code>, which is the top-left corner of pixel + * <code>(5,5)</code>.</p> * <p><b>Units</b>: * Pixels in the * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 0a0db235c677..47bef1256db9 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -2534,7 +2534,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * outputs will crop horizontally (pillarbox), and 16:9 * streams will match exactly. These additional crops will * be centered within the crop region.</p> - * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height + * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, the width and height * of the crop region cannot be set to be smaller than * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p> @@ -2875,8 +2875,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> new Key<Integer>("android.statistics.lensShadingMapMode", int.class); /** - * <p>A control for selecting whether OIS position information is included in output - * result metadata.</p> + * <p>A control for selecting whether optical stabilization (OIS) position + * information is included in output result metadata.</p> + * <p>Since optical image stabilization generally involves motion much faster than the duration + * of individualq image exposure, multiple OIS samples can be included for a single capture + * result. For example, if the OIS reporting operates at 200 Hz, a typical camera operating + * at 30fps may have 6-7 OIS samples per capture result. This information can be combined + * with the rolling shutter skew to account for lens motion during image exposure in + * post-processing algorithms.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li> @@ -3280,14 +3286,28 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * any correction at all would slow down capture rate. Every output stream will have a * similar amount of enhancement applied.</p> * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not - * applied to any RAW output. Metadata coordinates such as face rectangles or metering - * regions are also not affected by correction.</p> + * applied to any RAW output.</p> * <p>This control will be on by default on devices that support this control. Applications * disabling distortion correction need to pay extra attention with the coordinate system of * metering regions, crop region, and face rectangles. When distortion correction is OFF, * metadata coordinates follow the coordinate system of * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata - * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> + * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}. The + * camera device will map these metadata fields to match the corrected image produced by the + * camera device, for both capture requests and results. However, this mapping is not very + * precise, since rectangles do not generally map to rectangles when corrected. Only linear + * scaling between the active array and precorrection active array coordinates is + * performed. Applications that require precise correction of metadata need to undo that + * linear scaling, and apply a more complete correction that takes into the account the app's + * own requirements.</p> + * <p>The full list of metadata that is affected in this way by distortion correction is:</p> + * <ul> + * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li> + * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li> + * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li> + * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li> + * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li> + * </ul> * <p><b>Possible values:</b> * <ul> * <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li> @@ -3298,10 +3318,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * + * @see CaptureRequest#CONTROL_AE_REGIONS + * @see CaptureRequest#CONTROL_AF_REGIONS + * @see CaptureRequest#CONTROL_AWB_REGIONS * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES * @see CameraCharacteristics#LENS_DISTORTION + * @see CaptureRequest#SCALER_CROP_REGION * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE + * @see CaptureResult#STATISTICS_FACES * @see #DISTORTION_CORRECTION_MODE_OFF * @see #DISTORTION_CORRECTION_MODE_FAST * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index b03dfb67e903..bf890cec5319 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -2861,7 +2861,9 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>If this device is the largest or only camera device with a given facing, then this * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm * from the main sensor along the +X axis (to the right from the user's perspective) will - * report <code>(0.03, 0, 0)</code>.</p> + * report <code>(0.03, 0, 0)</code>. Note that this means that, for many computer vision + * applications, the position needs to be negated to convert it to a translation from the + * camera to the origin.</p> * <p>To transform a pixel coordinates between two cameras facing the same direction, first * the source camera {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} must be corrected for. Then the source * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the @@ -2873,7 +2875,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>To compare this against a real image from the destination camera, the destination camera * image then needs to be corrected for radial distortion before comparison or sampling.</p> * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to - * the center of the primary gyroscope on the device.</p> + * the center of the primary gyroscope on the device. The axis definitions are the same as + * with PRIMARY_CAMERA.</p> * <p><b>Units</b>: Meters</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * @@ -2905,13 +2908,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </code></pre> * <p>which can then be combined with the camera pose rotation * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and - * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the + * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respectively) to calculate the * complete transform from world coordinates to pixel * coordinates:</p> - * <pre><code>P = [ K 0 * [ R t - * 0 1 ] 0 1 ] + * <pre><code>P = [ K 0 * [ R -Rt + * 0 1 ] 0 1 ] * </code></pre> - * <p>and with <code>p_w</code> being a point in the world coordinate system + * <p>(Note the negation of poseTranslation when mapping from camera + * to world coordinates, and multiplication by the rotation).</p> + * <p>With <code>p_w</code> being a point in the world coordinate system * and <code>p_s</code> being a point in the camera active pixel array * coordinate system, and with the mapping including the * homogeneous division by z:</p> @@ -2933,6 +2938,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * activeArraySize rectangle), to determine the final pixel * coordinate of the world point for processed (non-RAW) * output buffers.</p> + * <p>For camera devices, the center of pixel <code>(x,y)</code> is located at + * coordinate <code>(x + 0.5, y + 0.5)</code>. So on a device with a + * precorrection active array of size <code>(10,10)</code>, the valid pixel + * indices go from <code>(0,0)-(9,9)</code>, and an perfectly-built camera would + * have an optical center at the exact center of the pixel grid, at + * coordinates <code>(5.0, 5.0)</code>, which is the top-left corner of pixel + * <code>(5,5)</code>.</p> * <p><b>Units</b>: * Pixels in the * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} @@ -3200,7 +3212,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * outputs will crop horizontally (pillarbox), and 16:9 * streams will match exactly. These additional crops will * be centered within the crop region.</p> - * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height + * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, the width and height * of the crop region cannot be set to be smaller than * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p> @@ -4096,8 +4108,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { new Key<Integer>("android.statistics.lensShadingMapMode", int.class); /** - * <p>A control for selecting whether OIS position information is included in output - * result metadata.</p> + * <p>A control for selecting whether optical stabilization (OIS) position + * information is included in output result metadata.</p> + * <p>Since optical image stabilization generally involves motion much faster than the duration + * of individualq image exposure, multiple OIS samples can be included for a single capture + * result. For example, if the OIS reporting operates at 200 Hz, a typical camera operating + * at 30fps may have 6-7 OIS samples per capture result. This information can be combined + * with the rolling shutter skew to account for lens motion during image exposure in + * post-processing algorithms.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li> @@ -4132,11 +4150,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>An array of shifts of OIS samples, in x direction.</p> * <p>The array contains the amount of shifts in x direction, in pixels, based on OIS samples. - * A positive value is a shift from left to right in active array coordinate system. For - * example, if the optical center is (1000, 500) in active array coordinates, a shift of - * (3, 0) puts the new optical center at (1003, 500).</p> + * A positive value is a shift from left to right in the pre-correction active array + * coordinate system. For example, if the optical center is (1000, 500) in pre-correction + * active array coordinates, a shift of (3, 0) puts the new optical center at (1003, 500).</p> * <p>The number of shifts must match the number of timestamps in * android.statistics.oisTimestamps.</p> + * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on + * supporting devices). They are always reported in pre-correction active array coordinates, + * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift + * is needed.</p> * <p><b>Units</b>: Pixels in active array.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * @hide @@ -4148,11 +4170,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { /** * <p>An array of shifts of OIS samples, in y direction.</p> * <p>The array contains the amount of shifts in y direction, in pixels, based on OIS samples. - * A positive value is a shift from top to bottom in active array coordinate system. For - * example, if the optical center is (1000, 500) in active array coordinates, a shift of - * (0, 5) puts the new optical center at (1000, 505).</p> + * A positive value is a shift from top to bottom in pre-correction active array coordinate + * system. For example, if the optical center is (1000, 500) in active array coordinates, a + * shift of (0, 5) puts the new optical center at (1000, 505).</p> * <p>The number of shifts must match the number of timestamps in * android.statistics.oisTimestamps.</p> + * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on + * supporting devices). They are always reported in pre-correction active array coordinates, + * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift + * is needed.</p> * <p><b>Units</b>: Pixels in active array.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * @hide @@ -4162,15 +4188,21 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { new Key<float[]>("android.statistics.oisYShifts", float[].class); /** - * <p>An array of OIS samples.</p> + * <p>An array of optical stabilization (OIS) position samples.</p> * <p>Each OIS sample contains the timestamp and the amount of shifts in x and y direction, * in pixels, of the OIS sample.</p> - * <p>A positive value for a shift in x direction is a shift from left to right in active array - * coordinate system. For example, if the optical center is (1000, 500) in active array - * coordinates, a shift of (3, 0) puts the new optical center at (1003, 500).</p> - * <p>A positive value for a shift in y direction is a shift from top to bottom in active array - * coordinate system. For example, if the optical center is (1000, 500) in active array - * coordinates, a shift of (0, 5) puts the new optical center at (1000, 505).</p> + * <p>A positive value for a shift in x direction is a shift from left to right in the + * pre-correction active array coordinate system. For example, if the optical center is + * (1000, 500) in pre-correction active array coordinates, a shift of (3, 0) puts the new + * optical center at (1003, 500).</p> + * <p>A positive value for a shift in y direction is a shift from top to bottom in + * pre-correction active array coordinate system. For example, if the optical center is + * (1000, 500) in active array coordinates, a shift of (0, 5) puts the new optical center at + * (1000, 505).</p> + * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on + * supporting devices). They are always reported in pre-correction active array coordinates, + * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift + * is needed.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> */ @PublicKey @@ -4605,14 +4637,28 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * any correction at all would slow down capture rate. Every output stream will have a * similar amount of enhancement applied.</p> * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not - * applied to any RAW output. Metadata coordinates such as face rectangles or metering - * regions are also not affected by correction.</p> + * applied to any RAW output.</p> * <p>This control will be on by default on devices that support this control. Applications * disabling distortion correction need to pay extra attention with the coordinate system of * metering regions, crop region, and face rectangles. When distortion correction is OFF, * metadata coordinates follow the coordinate system of * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata - * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> + * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}. The + * camera device will map these metadata fields to match the corrected image produced by the + * camera device, for both capture requests and results. However, this mapping is not very + * precise, since rectangles do not generally map to rectangles when corrected. Only linear + * scaling between the active array and precorrection active array coordinates is + * performed. Applications that require precise correction of metadata need to undo that + * linear scaling, and apply a more complete correction that takes into the account the app's + * own requirements.</p> + * <p>The full list of metadata that is affected in this way by distortion correction is:</p> + * <ul> + * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li> + * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li> + * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li> + * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li> + * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li> + * </ul> * <p><b>Possible values:</b> * <ul> * <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li> @@ -4623,10 +4669,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * + * @see CaptureRequest#CONTROL_AE_REGIONS + * @see CaptureRequest#CONTROL_AF_REGIONS + * @see CaptureRequest#CONTROL_AWB_REGIONS * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES * @see CameraCharacteristics#LENS_DISTORTION + * @see CaptureRequest#SCALER_CROP_REGION * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE + * @see CaptureResult#STATISTICS_FACES * @see #DISTORTION_CORRECTION_MODE_OFF * @see #DISTORTION_CORRECTION_MODE_FAST * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 40d53b741d6b..f033268698e6 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -329,6 +329,14 @@ public class TrafficStats { /** * Remove any statistics parameters from the given {@link Socket}. + * <p> + * In Android 8.1 (API level 27) and lower, a socket is automatically + * untagged when it's sent to another process using binder IPC with a + * {@code ParcelFileDescriptor} container. In Android 9.0 (API level 28) + * and higher, the socket tag is kept when the socket is sent to another + * process using binder IPC. You can mimic the previous behavior by + * calling {@code untagSocket()} before sending the socket to another + * process. */ public static void untagSocket(Socket socket) throws SocketException { SocketTagger.get().untag(socket); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 66f940801a2e..66487613fea5 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -628,7 +628,8 @@ public class Build { * October 2013: Android 4.4, KitKat, another tasty treat. * * <p>Applications targeting this or a later release will get these - * new changes in behavior:</p> + * new changes in behavior. For more information about this release, see the + * <a href="/about/versions/kitkat/">Android KitKat overview</a>.</p> * <ul> * <li> The default result of * {@link android.preference.PreferenceActivity#isValidFragment(String) @@ -678,7 +679,8 @@ public class Build { * November 2014: Lollipop. A flat one with beautiful shadows. But still tasty. * * <p>Applications targeting this or a later release will get these - * new changes in behavior:</p> + * new changes in behavior. For more information about this release, see the + * <a href="/about/versions/lollipop/">Android Lollipop overview</a>.</p> * <ul> * <li> {@link android.content.Context#bindService Context.bindService} now * requires an explicit Intent, and will throw an exception if given an implicit @@ -707,6 +709,8 @@ public class Build { /** * March 2015: Lollipop with an extra sugar coating on the outside! + * For more information about this release, see the + * <a href="/about/versions/android-5.1">Android 5.1 APIs</a>. */ public static final int LOLLIPOP_MR1 = 22; @@ -714,7 +718,8 @@ public class Build { * M is for Marshmallow! * * <p>Applications targeting this or a later release will get these - * new changes in behavior:</p> + * new changes in behavior. For more information about this release, see the + * <a href="/about/versions/marshmallow/">Android 6.0 Marshmallow overview</a>.</p> * <ul> * <li> Runtime permissions. Dangerous permissions are no longer granted at * install time, but must be requested by the application at runtime through @@ -745,7 +750,8 @@ public class Build { * N is for Nougat. * * <p>Applications targeting this or a later release will get these - * new changes in behavior:</p> + * new changes in behavior. For more information about this release, see + * the <a href="/about/versions/nougat/">Android Nougat overview</a>.</p> * <ul> * <li> {@link android.app.DownloadManager.Request#setAllowedNetworkTypes * DownloadManager.Request.setAllowedNetworkTypes} @@ -795,7 +801,9 @@ public class Build { public static final int N = 24; /** - * N MR1: Nougat++. + * N MR1: Nougat++. For more information about this release, see + * <a href="/about/versions/nougat/android-7.1">Android 7.1 for + * Developers</a>. */ public static final int N_MR1 = 25; @@ -803,7 +811,8 @@ public class Build { * O. * * <p>Applications targeting this or a later release will get these - * new changes in behavior:</p> + * new changes in behavior. For more information about this release, see + * the <a href="/about/versions/oreo/">Android Oreo overview</a>.</p> * <ul> * <li><a href="{@docRoot}about/versions/oreo/background.html">Background execution limits</a> * are applied to the application.</li> @@ -892,13 +901,16 @@ public class Build { * O MR1. * * <p>Applications targeting this or a later release will get these - * new changes in behavior:</p> + * new changes in behavior. For more information about this release, see + * <a href="/about/versions/oreo/android-8.1">Android 8.1 features and + * APIs</a>.</p> * <ul> * <li>Apps exporting and linking to apk shared libraries must explicitly * enumerate all signing certificates in a consistent order.</li> * <li>{@link android.R.attr#screenOrientation} can not be used to request a fixed * orientation if the associated activity is not fullscreen and opaque.</li> * </ul> + * */ public static final int O_MR1 = 27; @@ -906,7 +918,8 @@ public class Build { * P. * * <p>Applications targeting this or a later release will get these - * new changes in behavior:</p> + * new changes in behavior. For more information about this release, see the + * <a href="/about/versions/pie/">Android 9 Pie overview</a>.</p> * <ul> * <li>{@link android.app.Service#startForeground Service.startForeground} requires * that apps hold the permission @@ -914,6 +927,7 @@ public class Build { * <li>{@link android.widget.LinearLayout} will always remeasure weighted children, * even if there is no excess space.</li> * </ul> + * */ public static final int P = 28; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2439d23ced78..7b6b49d5356b 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10518,6 +10518,15 @@ public final class Settings { public static final String ACTIVITY_MANAGER_CONSTANTS = "activity_manager_constants"; /** + * Feature flag to enable or disable the activity starts logging feature. + * Type: int (0 for false, 1 for true) + * Default: 0 + * @hide + */ + public static final String ACTIVITY_STARTS_LOGGING_ENABLED + = "activity_starts_logging_enabled"; + + /** * App ops specific settings. * This is encoded as a key=value list, separated by commas. Ex: * diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java index b6c6bdc00bbe..5a7a83f19b0c 100644 --- a/core/java/android/service/notification/Condition.java +++ b/core/java/android/service/notification/Condition.java @@ -151,14 +151,14 @@ public final class Condition implements Parcelable { @Override public String toString() { return new StringBuilder(Condition.class.getSimpleName()).append('[') - .append("id=").append(id) - .append(",summary=").append(summary) - .append(",line1=").append(line1) - .append(",line2=").append(line2) - .append(",icon=").append(icon) - .append(",state=").append(stateToString(state)) - .append(",flags=").append(flags) - .append(']').toString(); + .append("state=").append(stateToString(state)) + .append(",id=").append(id) + .append(",summary=").append(summary) + .append(",line1=").append(line1) + .append(",line2=").append(line2) + .append(",icon=").append(icon) + .append(",flags=").append(flags) + .append(']').toString(); } /** @hide */ diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 5546e803342b..5edf7ce47658 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -240,11 +240,29 @@ public class ZenModeConfig implements Parcelable { .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom)) .append(",suppressedVisualEffects=").append(suppressedVisualEffects) .append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd) - .append(",automaticRules=").append(automaticRules) - .append(",manualRule=").append(manualRule) + .append(",\nautomaticRules=").append(rulesToString()) + .append(",\nmanualRule=").append(manualRule) .append(']').toString(); } + private String rulesToString() { + if (automaticRules.isEmpty()) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(automaticRules.size() * 28); + buffer.append('{'); + for (int i = 0; i < automaticRules.size(); i++) { + if (i > 0) { + buffer.append(",\n"); + } + Object value = automaticRules.valueAt(i); + buffer.append(value); + } + buffer.append('}'); + return buffer.toString(); + } + private Diff diff(ZenModeConfig to) { final Diff d = new Diff(); if (to == null) { @@ -1009,10 +1027,10 @@ public class ZenModeConfig implements Parcelable { public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) { final boolean isSchedule = conditionId != null - && conditionId.getScheme().equals(Condition.SCHEME) - && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY) + && Condition.SCHEME.equals(conditionId.getScheme()) + && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority()) && conditionId.getPathSegments().size() == 1 - && conditionId.getPathSegments().get(0).equals(ZenModeConfig.SCHEDULE_PATH); + && ZenModeConfig.SCHEDULE_PATH.equals(conditionId.getPathSegments().get(0)); if (!isSchedule) return null; final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start")); final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end")); @@ -1110,10 +1128,10 @@ public class ZenModeConfig implements Parcelable { public static EventInfo tryParseEventConditionId(Uri conditionId) { final boolean isEvent = conditionId != null - && conditionId.getScheme().equals(Condition.SCHEME) - && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY) + && Condition.SCHEME.equals(conditionId.getScheme()) + && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority()) && conditionId.getPathSegments().size() == 1 - && conditionId.getPathSegments().get(0).equals(EVENT_PATH); + && EVENT_PATH.equals(conditionId.getPathSegments().get(0)); if (!isEvent) return null; final EventInfo rt = new EventInfo(); rt.userId = tryParseInt(conditionId.getQueryParameter("userId"), UserHandle.USER_NULL); @@ -1322,14 +1340,14 @@ public class ZenModeConfig implements Parcelable { @Override public String toString() { return new StringBuilder(ZenRule.class.getSimpleName()).append('[') - .append("enabled=").append(enabled) + .append("id=").append(id) + .append(",enabled=").append(String.valueOf(enabled).toUpperCase()) .append(",snoozing=").append(snoozing) .append(",name=").append(name) .append(",zenMode=").append(Global.zenModeToString(zenMode)) .append(",conditionId=").append(conditionId) .append(",condition=").append(condition) .append(",component=").append(component) - .append(",id=").append(id) .append(",creationTime=").append(creationTime) .append(",enabler=").append(enabler) .append(']').toString(); @@ -1461,7 +1479,7 @@ public class ZenModeConfig implements Parcelable { final int N = lines.size(); for (int i = 0; i < N; i++) { if (i > 0) { - sb.append(','); + sb.append(",\n"); } sb.append(lines.get(i)); } diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java index b3400ef538b8..af18caa0e122 100644 --- a/core/java/android/util/SparseArray.java +++ b/core/java/android/util/SparseArray.java @@ -22,32 +22,34 @@ import com.android.internal.util.GrowingArrayUtils; import libcore.util.EmptyArray; /** - * SparseArrays map integers to Objects. Unlike a normal array of Objects, - * there can be gaps in the indices. It is intended to be more memory efficient - * than using a HashMap to map Integers to Objects, both because it avoids + * <code>SparseArray</code> maps integers to Objects and, unlike a normal array of Objects, + * its indices can contain gaps. <code>SparseArray</code> is intended to be more memory-efficient + * than a + * <a href="/reference/java/util/HashMap"><code>HashMap</code></a>, because it avoids * auto-boxing keys and its data structure doesn't rely on an extra entry object * for each mapping. * * <p>Note that this container keeps its mappings in an array data structure, - * using a binary search to find keys. The implementation is not intended to be appropriate for + * using a binary search to find keys. The implementation is not intended to be appropriate for * data structures - * that may contain large numbers of items. It is generally slower than a traditional - * HashMap, since lookups require a binary search and adds and removes require inserting - * and deleting entries in the array. For containers holding up to hundreds of items, - * the performance difference is not significant, less than 50%.</p> + * that may contain large numbers of items. It is generally slower than a + * <code>HashMap</code> because lookups require a binary search, + * and adds and removes require inserting + * and deleting entries in the array. For containers holding up to hundreds of items, + * the performance difference is less than 50%. * * <p>To help with performance, the container includes an optimization when removing * keys: instead of compacting its array immediately, it leaves the removed entry marked - * as deleted. The entry can then be re-used for the same key, or compacted later in - * a single garbage collection step of all removed entries. This garbage collection will - * need to be performed at any time the array needs to be grown or the the map size or - * entry values are retrieved.</p> + * as deleted. The entry can then be re-used for the same key or compacted later in + * a single garbage collection of all removed entries. This garbage collection + * must be performed whenever the array needs to be grown, or when the map size or + * entry values are retrieved. * * <p>It is possible to iterate over the items in this container using * {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using - * <code>keyAt(int)</code> with ascending values of the index will return the - * keys in ascending order, or the values corresponding to the keys in ascending - * order in the case of <code>valueAt(int)</code>.</p> + * <code>keyAt(int)</code> with ascending values of the index returns the + * keys in ascending order. In the case of <code>valueAt(int)</code>, the + * values corresponding to the keys are returned in ascending order. */ public class SparseArray<E> implements Cloneable { private static final Object DELETED = new Object(); @@ -333,7 +335,7 @@ public class SparseArray<E> implements Cloneable { /** * Returns an index for which {@link #valueAt} would return the - * specified key, or a negative number if no keys map to the + * specified value, or a negative number if no keys map to the * specified value. * <p>Beware that this is a linear search, unlike lookups by key, * and that multiple keys can map to the same value and this will @@ -357,7 +359,7 @@ public class SparseArray<E> implements Cloneable { /** * Returns an index for which {@link #valueAt} would return the - * specified key, or a negative number if no keys map to the + * specified value, or a negative number if no keys map to the * specified value. * <p>Beware that this is a linear search, unlike lookups by key, * and that multiple keys can map to the same value and this will diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index fc34a25cabc9..67e06e7b2c98 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1693,6 +1693,15 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_IS_SCREEN_DECOR = 0x00400000; /** + * Flag to indicate that the status bar window is now in an explicit expanded state, meaning + * that status bar will not be hidden by any window with flag {@link #FLAG_FULLSCREEN} or + * {@link View#SYSTEM_UI_FLAG_FULLSCREEN} set. + * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}. + * @hide + */ + public static final int PRIVATE_FLAG_STATUS_BAR_EXPANDED = 0x00800000; + + /** * Control flags that are private to the platform. * @hide */ @@ -1780,7 +1789,11 @@ public interface WindowManager extends ViewManager { @ViewDebug.FlagToString( mask = PRIVATE_FLAG_IS_SCREEN_DECOR, equals = PRIVATE_FLAG_IS_SCREEN_DECOR, - name = "IS_SCREEN_DECOR") + name = "IS_SCREEN_DECOR"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_STATUS_BAR_EXPANDED, + equals = PRIVATE_FLAG_STATUS_BAR_EXPANDED, + name = "STATUS_BAR_EXPANDED") }) @TestApi public int privateFlags; diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index f686b6645655..bdd7a0900213 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -31,18 +31,25 @@ import java.lang.annotation.RetentionPolicy; public class WebViewClient { /** - * Give the host application a chance to take over the control when a new - * url is about to be loaded in the current WebView. If WebViewClient is not - * provided, by default WebView will ask Activity Manager to choose the - * proper handler for the url. If WebViewClient is provided, return {@code true} - * means the host application handles the url, while return {@code false} means the - * current WebView handles the url. - * This method is not called for requests using the POST "method". + * Give the host application a chance to take control when a URL is about to be loaded in the + * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity + * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning + * {@code true} causes the current WebView to abort loading the URL, while returning + * {@code false} causes the WebView to continue loading the URL as usual. + * + * <p class="note"><b>Note:</b> Do not call {@link WebView#loadUrl(String)} with the same + * URL and then return {@code true}. This unnecessarily cancels the current load and starts a + * new load with the same URL. The correct way to continue loading a given URL is to simply + * return {@code false}, without calling {@link WebView#loadUrl(String)}. + * + * <p class="note"><b>Note:</b> This method is not called for POST requests. + * + * <p class="note"><b>Note:</b> This method may be called for subframes and with non-HTTP(S) + * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail. * * @param view The WebView that is initiating the callback. - * @param url The url to be loaded. - * @return {@code true} if the host application wants to leave the current WebView - * and handle the url itself, otherwise return {@code false}. + * @param url The URL to be loaded. + * @return {@code true} to cancel the current load, otherwise return {@code false}. * @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest) * shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead. */ @@ -52,26 +59,25 @@ public class WebViewClient { } /** - * Give the host application a chance to take over the control when a new - * url is about to be loaded in the current WebView. If WebViewClient is not - * provided, by default WebView will ask Activity Manager to choose the - * proper handler for the url. If WebViewClient is provided, return {@code true} - * means the host application handles the url, while return {@code false} means the - * current WebView handles the url. - * - * <p>Notes: - * <ul> - * <li>This method is not called for requests using the POST "method".</li> - * <li>This method is also called for subframes with non-http schemes, thus it is - * strongly disadvised to unconditionally call {@link WebView#loadUrl(String)} - * with the request's url from inside the method and then return {@code true}, - * as this will make WebView to attempt loading a non-http url, and thus fail.</li> - * </ul> + * Give the host application a chance to take control when a URL is about to be loaded in the + * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity + * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning + * {@code true} causes the current WebView to abort loading the URL, while returning + * {@code false} causes the WebView to continue loading the URL as usual. + * + * <p class="note"><b>Note:</b> Do not call {@link WebView#loadUrl(String)} with the request's + * URL and then return {@code true}. This unnecessarily cancels the current load and starts a + * new load with the same URL. The correct way to continue loading a given URL is to simply + * return {@code false}, without calling {@link WebView#loadUrl(String)}. + * + * <p class="note"><b>Note:</b> This method is not called for POST requests. + * + * <p class="note"><b>Note:</b> This method may be called for subframes and with non-HTTP(S) + * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail. * * @param view The WebView that is initiating the callback. * @param request Object containing the details of the request. - * @return {@code true} if the host application wants to leave the current WebView - * and handle the url itself, otherwise return {@code false}. + * @return {@code true} to cancel the current load, otherwise return {@code false}. */ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return shouldOverrideUrlLoading(view, request.getUrl().toString()); diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 398d08791b5c..4728124c17c5 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -16,14 +16,21 @@ package com.android.internal.app; +import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; + +import android.annotation.Nullable; +import android.annotation.StringRes; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.admin.DevicePolicyManager; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.RemoteException; @@ -31,12 +38,11 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; import android.widget.Toast; - import com.android.internal.annotations.VisibleForTesting; - +import java.util.Arrays; +import java.util.HashSet; import java.util.List; - -import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; +import java.util.Set; /** * This is used in conjunction with @@ -44,7 +50,6 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; * be passed in and out of a managed profile. */ public class IntentForwarderActivity extends Activity { - public static String TAG = "IntentForwarderActivity"; public static String FORWARD_INTENT_TO_PARENT @@ -53,6 +58,9 @@ public class IntentForwarderActivity extends Activity { public static String FORWARD_INTENT_TO_MANAGED_PROFILE = "com.android.internal.app.ForwardIntentToManagedProfile"; + private static final Set<String> ALLOWED_TEXT_MESSAGE_SCHEME + = new HashSet<>(Arrays.asList("sms", "smsto", "mms", "mmsto")); + private Injector mInjector; @Override @@ -93,19 +101,8 @@ public class IntentForwarderActivity extends Activity { newIntent.prepareToLeaveUser(callingUserId); } - final android.content.pm.ResolveInfo ri = - mInjector.getPackageManager().resolveActivityAsUser( - newIntent, - MATCH_DEFAULT_ONLY, - targetUserId); - - // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity - // as those will already have shown work / personal as neccesary etc. - final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null || - !"android".equals(ri.activityInfo.packageName) || - !(ResolverActivity.class.getName().equals(ri.activityInfo.name) - || ChooserActivity.class.getName().equals(ri.activityInfo.name)); - + final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, + targetUserId); try { startActivityAsCaller(newIntent, null, false, targetUserId); } catch (RuntimeException e) { @@ -124,8 +121,8 @@ public class IntentForwarderActivity extends Activity { + ActivityThread.currentProcessName(), e); } - if (shouldShowDisclosure) { - Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); + if (shouldShowDisclosure(ri, intentReceived)) { + mInjector.showToast(userMessageId, Toast.LENGTH_LONG); } } else { Slog.wtf(TAG, "the intent: " + intentReceived + " cannot be forwarded from user " @@ -134,6 +131,35 @@ public class IntentForwarderActivity extends Activity { finish(); } + private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) { + if (ri == null || ri.activityInfo == null) { + return true; + } + if (ri.activityInfo.applicationInfo.isSystemApp() + && (isDialerIntent(intent) || isTextMessageIntent(intent))) { + return false; + } + return !isTargetResolverOrChooserActivity(ri.activityInfo); + } + + private boolean isTextMessageIntent(Intent intent) { + return Intent.ACTION_SENDTO.equals(intent.getAction()) && intent.getData() != null + && ALLOWED_TEXT_MESSAGE_SCHEME.contains(intent.getData().getScheme()); + } + + private boolean isDialerIntent(Intent intent) { + return Intent.ACTION_DIAL.equals(intent.getAction()) + || Intent.ACTION_CALL.equals(intent.getAction()); + } + + private boolean isTargetResolverOrChooserActivity(ActivityInfo activityInfo) { + if (!"android".equals(activityInfo.packageName)) { + return false; + } + return ResolverActivity.class.getName().equals(activityInfo.name) + || ChooserActivity.class.getName().equals(activityInfo.name); + } + /** * Check whether the intent can be forwarded to target user. Return the intent used for * forwarding if it can be forwarded, {@code null} otherwise. @@ -241,6 +267,16 @@ public class IntentForwarderActivity extends Activity { public PackageManager getPackageManager() { return IntentForwarderActivity.this.getPackageManager(); } + + @Override + public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { + return getPackageManager().resolveActivityAsUser(intent, flags, userId); + } + + @Override + public void showToast(int messageId, int duration) { + Toast.makeText(IntentForwarderActivity.this, getString(messageId), duration).show(); + } } public interface Injector { @@ -249,5 +285,9 @@ public class IntentForwarderActivity extends Activity { UserManager getUserManager(); PackageManager getPackageManager(); + + ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId); + + void showToast(@StringRes int messageId, int duration); } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 4cc91ec3ae72..50d3a56454df 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -4021,7 +4021,9 @@ public class BatteryStatsImpl extends BatteryStats { try { IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface( ServiceManager.getService("batteryproperties")); - registrar.scheduleUpdate(); + if (registrar != null) { + registrar.scheduleUpdate(); + } } catch (RemoteException e) { // Ignore. } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 778e4c4e3797..4b9a82e20170 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -670,6 +670,10 @@ <!-- Boolean indicating whether framework needs to set the tx power limit for meeting SAR requirements --> <bool translatable="false" name="config_wifi_framework_enable_sar_tx_power_limit">false</bool> + <!-- Boolean indicating whether framework should use detection of softAP mode to set the tx + power limit for meeting SAR requirements --> + <bool translatable="false" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit">false</bool> + <!-- Boolean indicating whether framework needs to use body proximity to set the tx power limit for meeting SAR requirements --> <bool translatable="false" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit">false</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5119e2cb8cae..00bd77d32935 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -337,6 +337,7 @@ <java-symbol type="bool" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection" /> <java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" /> <java-symbol type="bool" name="config_wifi_framework_enable_sar_tx_power_limit" /> + <java-symbol type="bool" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit" /> <java-symbol type="bool" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit" /> <java-symbol type="string" name="config_wifi_sar_sensor_type" /> <java-symbol type="integer" name="config_wifi_framework_sar_free_space_event_id" /> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index e50efa970f3b..a04bf0264dde 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -99,6 +99,7 @@ public class SettingsBackupTest { private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS = newHashSet( Settings.Global.ACTIVITY_MANAGER_CONSTANTS, + Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, Settings.Global.ADB_ENABLED, Settings.Global.ADD_USERS_WHEN_LOCKED, diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java index b18fa747557d..c165b6be525e 100644 --- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java @@ -16,46 +16,50 @@ package com.android.internal.app; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.net.Uri; import android.os.Bundle; +import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; -import android.util.Log; - +import java.util.ArrayList; +import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import java.util.ArrayList; -import java.util.List; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(AndroidJUnit4.class) public class IntentForwarderActivityTest { + private static final ComponentName FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME = new ComponentName( "android", @@ -77,22 +81,26 @@ public class IntentForwarderActivityTest { private static IntentForwarderActivity.Injector sInjector; private static ComponentName sComponentName; + private static String sActivityName; + private static String sPackageName; @Mock private IPackageManager mIPm; @Mock private PackageManager mPm; @Mock private UserManager mUserManager; + @Mock private ApplicationInfo mApplicationInfo; @Rule public ActivityTestRule<IntentForwarderWrapperActivity> mActivityRule = new ActivityTestRule<>(IntentForwarderWrapperActivity.class, true, false); private Context mContext; + public static final String PHONE_NUMBER = "123-456-789"; @Before public void setup() { MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); - sInjector = new TestInjector(); + sInjector = spy(new TestInjector()); } @Test @@ -252,6 +260,149 @@ public class IntentForwarderActivityTest { assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn); } + @Test + public void shouldSkipDisclosure_notWhitelisted() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_SEND) + .setType(TYPE_PLAIN_TEXT); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_withResolverActivity() throws RemoteException { + setupShouldSkipDisclosureTest(); + sActivityName = ResolverActivity.class.getName(); + sPackageName = "android"; + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_SEND) + .setType(TYPE_PLAIN_TEXT); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector, never()).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_callIntent_call() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_CALL); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector, never()).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_callIntent_dial() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_DIAL); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector, never()).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_callIntent_notCallOrDial() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_ALARM_CHANGED); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_textMessageIntent_sms() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_SENDTO) + .setData(Uri.fromParts("sms", PHONE_NUMBER, null)); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector, never()).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_textMessageIntent_smsto() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_SENDTO) + .setData(Uri.fromParts("smsto", PHONE_NUMBER, null)); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector, never()).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_textMessageIntent_mms() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_SENDTO) + .setData(Uri.fromParts("mms", PHONE_NUMBER, null)); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector, never()).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_textMessageIntent_mmsto() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_SENDTO) + .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null)); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector, never()).showToast(anyInt(), anyInt()); + } + + @Test + public void shouldSkipDisclosure_textMessageIntent_invalidUri() throws RemoteException { + setupShouldSkipDisclosureTest(); + Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) + .setAction(Intent.ACTION_SENDTO) + .setData(Uri.fromParts("invalid", PHONE_NUMBER, null)); + + mActivityRule.launchActivity(intent); + + verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); + verify(sInjector).showToast(anyInt(), anyInt()); + } + + private void setupShouldSkipDisclosureTest() throws RemoteException { + sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; + sActivityName = "MyTestActivity"; + sPackageName = "test.package.name"; + when(mApplicationInfo.isSystemApp()).thenReturn(true); + // Managed profile exists. + List<UserInfo> profiles = new ArrayList<>(); + profiles.add(CURRENT_USER_INFO); + profiles.add(MANAGED_PROFILE_INFO); + when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); + // Intent can be forwarded. + when(mIPm.canForwardTo( + any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); + } public static class IntentForwarderWrapperActivity extends IntentForwarderActivity { private Intent mStartActivityIntent; @@ -276,7 +427,7 @@ public class IntentForwarderActivityTest { } } - class TestInjector implements IntentForwarderActivity.Injector { + public class TestInjector implements IntentForwarderActivity.Injector { @Override public IPackageManager getIPackageManager() { @@ -292,5 +443,21 @@ public class IntentForwarderActivityTest { public PackageManager getPackageManager() { return mPm; } + + @Override + public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { + ActivityInfo activityInfo = new ActivityInfo(); + activityInfo.packageName = sPackageName; + activityInfo.name = sActivityName; + activityInfo.applicationInfo = mApplicationInfo; + + ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.activityInfo = activityInfo; + + return resolveInfo; + } + + @Override + public void showToast(int messageId, int duration) {} } }
\ No newline at end of file diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 2503381a501f..ef58c8f2bd16 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1600,9 +1600,9 @@ public class Canvas extends BaseCanvas { * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be * drawn. The circle will be filled or framed based on the Style in the paint. * - * @param cx The x-coordinate of the center of the cirle to be drawn - * @param cy The y-coordinate of the center of the cirle to be drawn - * @param radius The radius of the cirle to be drawn + * @param cx The x-coordinate of the center of the circle to be drawn + * @param cy The y-coordinate of the center of the circle to be drawn + * @param radius The radius of the circle to be drawn * @param paint The paint used to draw the circle */ public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index cb5a0507815b..b1a247a59dc7 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -142,6 +142,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mSecurityViewFlipper.addView(v); updateSecurityView(v); view = (KeyguardSecurityView)v; + view.reset(); } return view; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 306319903ecb..a215ec6ecafa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -151,12 +151,11 @@ public class NotificationShelf extends ActivatableNotificationView implements } public void fadeInTranslating() { - float translation = mShelfIcons.getTranslationY(); - mShelfIcons.setTranslationY(translation - mShelfAppearTranslation); + mShelfIcons.setTranslationY(-mShelfAppearTranslation); mShelfIcons.setAlpha(0); mShelfIcons.animate() .setInterpolator(Interpolators.DECELERATE_QUINT) - .translationY(translation) + .translationY(0) .setDuration(SHELF_IN_TRANSLATION_DURATION) .start(); mShelfIcons.animate() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 7e6abe95e226..5c18782727df 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1358,9 +1358,7 @@ public class NotificationPanelView extends PanelView implements mQsExpansionHeight = height; updateQsExpansion(); requestScrollerTopPaddingUpdate(false /* animate */); - if (mKeyguardShowing) { - updateHeaderKeyguardAlpha(); - } + updateHeaderKeyguardAlpha(); if (mStatusBarState == StatusBarState.SHADE_LOCKED || mStatusBarState == StatusBarState.KEYGUARD) { updateKeyguardBottomAreaAlpha(); @@ -1763,6 +1761,9 @@ public class NotificationPanelView extends PanelView implements } private void updateHeaderKeyguardAlpha() { + if (!mKeyguardShowing) { + return; + } float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2); mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion) * mKeyguardStatusBarAnimateAlpha); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index fadc0eac9e73..a38328a8161e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -180,6 +180,15 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; } + private void applyExpandedFlag(State state) { + if (state.panelExpanded || state.isKeyguardShowingAndNotOccluded() || state.bouncerShowing + || ENABLE_REMOTE_INPUT && state.remoteInputActive) { + mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; + } else { + mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; + } + } + private void applyHeight(State state) { boolean expanded = isExpanded(state); if (state.forcePluginOpen) { @@ -234,6 +243,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D applyKeyguardFlags(state); applyForceStatusBarVisibleFlag(state); applyFocusableFlag(state); + applyExpandedFlag(state); adjustScreenOrientation(state); applyHeight(state); applyUserActivityTimeout(state); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index d6d0673e2c0b..3c16329e6f19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -134,6 +134,10 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof @Override public void setHotspotEnabled(boolean enabled) { + if (mWaitingForCallback) { + if (DEBUG) Log.d(TAG, "Ignoring setHotspotEnabled; waiting for callback."); + return; + } if (enabled) { OnStartTetheringCallback callback = new OnStartTetheringCallback(); mWaitingForCallback = true; diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 143fa8634333..0833e34ff8b3 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -941,9 +941,10 @@ message MetricsEvent { // OS: 6.0 NOTIFICATION_ZEN_MODE_EVENT_RULE = 146; - // ACTION: App notification settings > Block Notifications + // ACTION: App notification settings > Block Notifications or long press on + // notification blocks. // CATEGORY: SETTINGS - // OS: 6.0 + // OS: 9.0 ACTION_BAN_APP_NOTES = 147; // ACTION: Notification shade > Dismiss all button @@ -6129,6 +6130,305 @@ message MetricsEvent { // CATEGORY: NOTIFICATION NOTIFICATION_INTERRUPTION = 1501; + // OPEN: Settings + // CATEGORY: SETTINGS + // OS: Q + SETTINGS_HOMEPAGE = 1502; + + // OPEN: Settings > Create shortcut(widget) + // CATEGORY: SETTINGS + // OS: Q + SETTINGS_CREATE_SHORTCUT = 1503; + + // ACTION: Authenticate using fingerprint + // CATEGORY: SETTINGS + // OS: Q + ACTION_FACE_AUTH = 1504; + + // ACTION: Add fingerprint > Enroll fingerprint + // CATEGORY: SETTINGS + // OS: Q + ACTION_FACE_ENROLL = 1505; + + // OPEN: Face Enroll introduction + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_INTRO = 1506; + + // OPEN: Face Enroll introduction + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_ENROLLING = 1507; + + // OPEN: Face Enroll introduction + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_FINISHED = 1508; + + // OPEN: Face Enroll sidecar + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_SIDECAR = 1509; + + // OPEN: Settings > Add face > Error dialog + // OS: Q + DIALOG_FACE_ERROR = 1510; + + // OPEN: Settings > Security > Face + // CATEGORY: SETTINGS + // OS: Q + FACE = 1511; + + // OPEN: Settings > Acessibility > HearingAid pairing instructions dialog + // CATEGORY: SETTINGS + // OS: Q + DIALOG_ACCESSIBILITY_HEARINGAID = 1512; + + // ACTION: Activity start + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + ACTION_ACTIVITY_START = 1513; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Calling UID + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_CALLING_UID = 1514; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Calling package name + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_CALLING_PACKAGE_NAME = 1515; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Calling UID proc state + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_CALLING_UID_PROC_STATE = 1516; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Calling UID has any visible window + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW = 1517; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Real calling UID + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_REAL_CALLING_UID = 1518; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Real calling UID proc state + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_REAL_CALLING_UID_PROC_STATE = 1519; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Real calling UID has any visible window + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW = 1520; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Target UID + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_TARGET_UID = 1521; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Target UID package name + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_TARGET_PACKAGE_NAME = 1522; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Target UID proc state + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_TARGET_UID_PROC_STATE = 1523; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Target UID has any visible window + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW = 1524; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Target doze whitelist tag + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_TARGET_WHITELIST_TAG = 1525; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Target short component name + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_TARGET_SHORT_COMPONENT_NAME = 1526; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Coming from pending intent + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_COMING_FROM_PENDING_INTENT = 1527; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Intent action + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_INTENT_ACTION = 1528; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record process name + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_PROCESS_NAME = 1529; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record current proc state + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_CUR_PROC_STATE = 1530; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record has client activities + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES = 1531; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record has foreground services + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES = 1532; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record has foreground activities + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES = 1533; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record has top UI + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_HAS_TOP_UI = 1534; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record has overlay UI + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_HAS_OVERLAY_UI = 1535; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Caller app process record pending UI clean + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_PENDING_UI_CLEAN = 1536; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Millis since caller app's process record last interaction event + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT = 1537; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Millis since caller app's process record fg interaction + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION = 1538; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Millis since caller app's process record last became unimportant + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT = 1539; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record launch mode + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_LAUNCH_MODE = 1540; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record target activity + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY = 1541; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record flags + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_FLAGS = 1542; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record real activity + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_REAL_ACTIVITY = 1543; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record short component name + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME = 1544; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record process name + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_PROCESS_NAME = 1545; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record is fullscreen + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_IS_FULLSCREEN = 1546; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record is no display + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY = 1547; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Millis since activity was last visible + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE = 1548; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record's resultTo packageName + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME = 1549; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record's resultTo shortComponentName + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME = 1550; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record is visible + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_IS_VISIBLE = 1551; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Activity record is visible ignoring keyguard + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD = 1552; + + // Tagged data for ACTION_ACTIVITY_START. + // FIELD: Millis since activity's last launch + // CATEGORY: OTHER + // OS: Q (will also ship in PQ1A) + FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH = 1553; + // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto index 72f11e0a63c1..a98996d84993 100644 --- a/proto/src/wifi.proto +++ b/proto/src/wifi.proto @@ -457,6 +457,8 @@ message WifiLog { // Identifier for experimental scoring parameter settings. optional string score_experiment_id = 117; + // Histogram of the EAP method type of all installed Passpoint profiles + repeated PasspointProfileTypeCount installed_passpoint_profile_type = 123; } // Information that gets logged for every WiFi connection. @@ -1503,3 +1505,31 @@ message WifiRttLog { optional int32 count = 2; } } + +message PasspointProfileTypeCount { + enum EapMethod { + // Unknown Type + TYPE_UNKNOWN = 0; + + // EAP_TLS (13) + TYPE_EAP_TLS = 1; + + // EAP_TTLS (21) + TYPE_EAP_TTLS = 2; + + // EAP_SIM (18) + TYPE_EAP_SIM = 3; + + // EAP_AKA (23) + TYPE_EAP_AKA = 4; + + // EAP_AKA_PRIME (50) + TYPE_EAP_AKA_PRIME = 5; + } + + // Eap method type set in Passpoint profile + optional EapMethod eap_method_type = 1; + + // Num of installed Passpoint profile with same eap method + optional int32 count = 2; +} diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index f5b29e9b76b8..a05a3e767d12 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -69,6 +69,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.List; import java.util.ArrayList; import java.util.zip.ZipFile; @@ -345,31 +346,76 @@ public final class PinnerService extends SystemService { } private ApplicationInfo getCameraInfo(int userHandle) { - // find the camera via an intent - // use INTENT_ACTION_STILL_IMAGE_CAMERA instead of _SECURE. On a - // device without a fbe enabled, the _SECURE intent will never get set. Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - return getApplicationInfoForIntent(cameraIntent, userHandle); + ApplicationInfo info = getApplicationInfoForIntent(cameraIntent, userHandle, + false /* defaultToSystemApp */); + + // If the STILL_IMAGE_CAMERA intent doesn't resolve, try the _SECURE intent. + // We don't use _SECURE first because it will never get set on a device + // without File-based Encryption. But if the user has only set the intent + // before unlocking their device, we may still be able to identify their + // preference using this intent. + if (info == null) { + cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); + info = getApplicationInfoForIntent(cameraIntent, userHandle, + false /* defaultToSystemApp */); + } + + // If the _SECURE intent doesn't resolve, try the original intent but request + // the system app for camera if there was more than one result. + if (info == null) { + cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + info = getApplicationInfoForIntent(cameraIntent, userHandle, + true /* defaultToSystemApp */); + } + return info; } private ApplicationInfo getHomeInfo(int userHandle) { Intent intent = mAmInternal.getHomeIntent(); - return getApplicationInfoForIntent(intent, userHandle); + return getApplicationInfoForIntent(intent, userHandle, false); } - private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle) { + private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle, + boolean defaultToSystemApp) { if (intent == null) { return null; } - ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(intent, + + ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivityAsUser(intent, MATCH_FLAGS, userHandle); - if (info == null) { + + // If this intent can resolve to only one app, choose that one. + // Otherwise, if we've requested to default to the system app, return it; + // if we have not requested that default, return null if there's more than one option. + // If there's more than one system app, return null since we don't know which to pick. + if (resolveInfo == null) { return null; } - if (isResolverActivity(info.activityInfo)) { - return null; + + if (!isResolverActivity(resolveInfo.activityInfo)) { + return resolveInfo.activityInfo.applicationInfo; + } + + if (defaultToSystemApp) { + List<ResolveInfo> infoList = mContext.getPackageManager() + .queryIntentActivitiesAsUser(intent, MATCH_FLAGS, userHandle); + ApplicationInfo systemAppInfo = null; + for (ResolveInfo info : infoList) { + if ((info.activityInfo.applicationInfo.flags + & ApplicationInfo.FLAG_SYSTEM) != 0) { + if (systemAppInfo == null) { + systemAppInfo = info.activityInfo.applicationInfo; + } else { + // If there's more than one system app, return null due to ambiguity. + return null; + } + } + } + return systemAppInfo; } - return info.activityInfo.applicationInfo; + + return null; } private void sendPinAppsMessage(int userHandle) { diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 6550d06b8a12..9bf72fb86cd6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -207,6 +207,10 @@ final class ActivityManagerConstants extends ContentObserver { // Indicates if the processes need to be started asynchronously. public boolean FLAG_PROCESS_START_ASYNC = DEFAULT_PROCESS_START_ASYNC; + // Indicates whether the activity starts logging is enabled. + // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED + boolean mFlagActivityStartsLoggingEnabled; + private final ActivityManagerService mService; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -235,6 +239,12 @@ final class ActivityManagerConstants extends ContentObserver { // memory trimming. public int CUR_TRIM_CACHED_PROCESSES; + private static final Uri ACTIVITY_MANAGER_CONSTANTS_URI = Settings.Global.getUriFor( + Settings.Global.ACTIVITY_MANAGER_CONSTANTS); + + private static final Uri ACTIVITY_STARTS_LOGGING_ENABLED_URI = Settings.Global.getUriFor( + Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED); + public ActivityManagerConstants(ActivityManagerService service, Handler handler) { super(handler); mService = service; @@ -243,9 +253,10 @@ final class ActivityManagerConstants extends ContentObserver { public void start(ContentResolver resolver) { mResolver = resolver; - mResolver.registerContentObserver(Settings.Global.getUriFor( - Settings.Global.ACTIVITY_MANAGER_CONSTANTS), false, this); + mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this); + mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this); updateConstants(); + updateActivityStartsLoggingEnabled(); } public void setOverrideMaxCachedProcesses(int value) { @@ -263,7 +274,12 @@ final class ActivityManagerConstants extends ContentObserver { @Override public void onChange(boolean selfChange, Uri uri) { - updateConstants(); + if (uri == null) return; + if (ACTIVITY_MANAGER_CONSTANTS_URI.equals(uri)) { + updateConstants(); + } else if (ACTIVITY_STARTS_LOGGING_ENABLED_URI.equals(uri)) { + updateActivityStartsLoggingEnabled(); + } } private void updateConstants() { @@ -337,6 +353,11 @@ final class ActivityManagerConstants extends ContentObserver { } } + private void updateActivityStartsLoggingEnabled() { + mFlagActivityStartsLoggingEnabled = Settings.Global.getInt(mResolver, + Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 0) == 1; + } + private void updateMaxCachedProcesses() { CUR_MAX_CACHED_PROCESSES = mOverrideMaxCachedProcesses < 0 ? MAX_CACHED_PROCESSES : mOverrideMaxCachedProcesses; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c3782d0d8f63..d403c28ba995 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5591,7 +5591,7 @@ public class ActivityManagerService extends IActivityManager.Stub // TODO: Switch to user app stacks here. int ret = mActivityStartController.startActivities(caller, -1, callingPackage, intents, resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, - reason); + reason, null /* originatingPendingIntent */); return ret; } @@ -9498,10 +9498,17 @@ public class ActivityManagerService extends IActivityManager.Stub } } - // If we're extending a persistable grant, then we always need to create - // the grant data structure so that take/release APIs work + // Figure out the value returned when access is allowed + final int allowedResult; if ((modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) { - return targetUid; + // If we're extending a persistable grant, then we need to return + // "targetUid" so that we always create a grant data structure to + // support take/release APIs + allowedResult = targetUid; + } else { + // Otherwise, we can return "-1" to indicate that no grant data + // structures need to be created + allowedResult = -1; } if (targetUid >= 0) { @@ -9510,7 +9517,7 @@ public class ActivityManagerService extends IActivityManager.Stub // No need to grant the target this permission. if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "Target " + targetPkg + " already has full permission to " + grantUri); - return -1; + return allowedResult; } } else { // First... there is no target package, so can anyone access it? @@ -9545,7 +9552,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (allowed) { - return -1; + return allowedResult; } } @@ -10927,6 +10934,20 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on + * the whitelist + */ + String getPendingTempWhitelistTagForUidLocked(int uid) { + final PendingTempWhitelist ptw = mPendingTempWhitelist.get(uid); + return ptw != null ? ptw.tag : null; + } + + @VisibleForTesting + boolean isActivityStartsLoggingEnabled() { + return mConstants.mFlagActivityStartsLoggingEnabled; + } + @Override public void moveStackToDisplay(int stackId, int displayId) { enforceCallingPermission(INTERNAL_SYSTEM_WINDOW, "moveStackToDisplay()"); @@ -26379,7 +26400,7 @@ public class ActivityManagerService extends IActivityManager.Stub packageUid, packageName, intents, resolvedTypes, null /* resultTo */, SafeActivityOptions.fromBundle(bOptions), userId, - false /* validateIncomingUser */); + false /* validateIncomingUser */, null /* originatingPendingIntent */); } } diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 47d0423550c4..9ffa6627836f 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -2,6 +2,7 @@ package com.android.server.am; import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; +import static android.app.ActivityManager.processStateAmToProto; import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -9,6 +10,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ACTIVITY_START; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME; @@ -21,8 +23,48 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TR import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_FLAGS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_FULLSCREEN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_PROCESS_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_REAL_ACTIVITY; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_PACKAGE_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_PROC_STATE; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_COMING_FROM_PENDING_INTENT; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INTENT_ACTION; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_CUR_PROC_STATE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_OVERLAY_UI; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_TOP_UI; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PENDING_UI_CLEAN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PROCESS_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_PACKAGE_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_SHORT_COMPONENT_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_PROC_STATE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_WHITELIST_TAG; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH; @@ -37,6 +79,7 @@ import static com.android.server.am.MemoryStatUtil.MemoryStat; import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; import android.content.Context; +import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.dex.ArtManagerInternal; import android.content.pm.dex.PackageOptimizationInfo; @@ -622,6 +665,95 @@ class ActivityMetricsLogger { startupTimeMs); } + void logActivityStart(Intent intent, ProcessRecord callerApp, ActivityRecord r, + int callingUid, String callingPackage, int callingUidProcState, + boolean callingUidHasAnyVisibleWindow, + int realCallingUid, int realCallingUidProcState, + boolean realCallingUidHasAnyVisibleWindow, + int targetUid, String targetPackage, int targetUidProcState, + boolean targetUidHasAnyVisibleWindow, String targetWhitelistTag, + boolean comingFromPendingIntent) { + + final long nowElapsed = SystemClock.elapsedRealtime(); + final long nowUptime = SystemClock.uptimeMillis(); + final LogMaker builder = new LogMaker(ACTION_ACTIVITY_START); + builder.setTimestamp(System.currentTimeMillis()); + builder.addTaggedData(FIELD_CALLING_UID, callingUid); + builder.addTaggedData(FIELD_CALLING_PACKAGE_NAME, callingPackage); + builder.addTaggedData(FIELD_CALLING_UID_PROC_STATE, + processStateAmToProto(callingUidProcState)); + builder.addTaggedData(FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW, + callingUidHasAnyVisibleWindow ? 1 : 0); + builder.addTaggedData(FIELD_REAL_CALLING_UID, realCallingUid); + builder.addTaggedData(FIELD_REAL_CALLING_UID_PROC_STATE, + processStateAmToProto(realCallingUidProcState)); + builder.addTaggedData(FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW, + realCallingUidHasAnyVisibleWindow ? 1 : 0); + builder.addTaggedData(FIELD_TARGET_UID, targetUid); + builder.addTaggedData(FIELD_TARGET_PACKAGE_NAME, targetPackage); + builder.addTaggedData(FIELD_TARGET_UID_PROC_STATE, + processStateAmToProto(targetUidProcState)); + builder.addTaggedData(FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW, + targetUidHasAnyVisibleWindow ? 1 : 0); + builder.addTaggedData(FIELD_TARGET_WHITELIST_TAG, targetWhitelistTag); + builder.addTaggedData(FIELD_TARGET_SHORT_COMPONENT_NAME, r.shortComponentName); + builder.addTaggedData(FIELD_COMING_FROM_PENDING_INTENT, comingFromPendingIntent ? 1 : 0); + builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction()); + if (callerApp != null) { + builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.processName); + builder.addTaggedData(FIELD_PROCESS_RECORD_CUR_PROC_STATE, + processStateAmToProto(callerApp.curProcState)); + builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES, + callerApp.hasClientActivities ? 1 : 0); + builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES, + callerApp.hasForegroundServices() ? 1 : 0); + builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES, + callerApp.foregroundActivities ? 1 : 0); + builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_TOP_UI, callerApp.hasTopUi ? 1 : 0); + builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_OVERLAY_UI, + callerApp.hasOverlayUi ? 1 : 0); + builder.addTaggedData(FIELD_PROCESS_RECORD_PENDING_UI_CLEAN, + callerApp.pendingUiClean ? 1 : 0); + if (callerApp.interactionEventTime != 0) { + builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT, + (nowElapsed - callerApp.interactionEventTime)); + } + if (callerApp.fgInteractionTime != 0) { + builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION, + (nowElapsed - callerApp.fgInteractionTime)); + } + if (callerApp.whenUnimportant != 0) { + builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT, + (nowUptime - callerApp.whenUnimportant)); + } + } + builder.addTaggedData(FIELD_ACTIVITY_RECORD_LAUNCH_MODE, r.info.launchMode); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY, r.info.targetActivity); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_FLAGS, r.info.flags); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_REAL_ACTIVITY, r.realActivity.toShortString()); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME, r.shortComponentName); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_PROCESS_NAME, r.processName); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_FULLSCREEN, r.fullscreen ? 1 : 0); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY, r.noDisplay ? 1 : 0); + if (r.lastVisibleTime != 0) { + builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE, + (nowUptime - r.lastVisibleTime)); + } + if (r.resultTo != null) { + builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME, r.resultTo.packageName); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME, + r.resultTo.shortComponentName); + } + builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE, r.visible ? 1 : 0); + builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD, + r.visibleIgnoringKeyguard ? 1 : 0); + if (r.lastLaunchTime != 0) { + builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH, + (nowUptime - r.lastLaunchTime)); + } + mMetricsLogger.write(builder); + } + private int getTransitionType(WindowingModeTransitionInfo info) { if (info.currentTransitionProcessRunning) { if (info.startResult == START_SUCCESS) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index c520101d3ff4..2ae056fe18a5 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -4853,7 +4853,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return mService.getActivityStartController().startActivityInPackage( task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null, null, 0, 0, options, userId, task, "startActivityFromRecents", - false /* validateIncomingUser */); + false /* validateIncomingUser */, null /* originatingPendingIntent */); } finally { if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && task != null) { // If we are launching the task in the docked stack, put it into resizing mode so diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java index a7c32009a4c4..edcf6e7bd516 100644 --- a/services/core/java/com/android/server/am/ActivityStartController.java +++ b/services/core/java/com/android/server/am/ActivityStartController.java @@ -248,7 +248,8 @@ public class ActivityStartController { final int startActivityInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, SafeActivityOptions options, - int userId, TaskRecord inTask, String reason, boolean validateIncomingUser) { + int userId, TaskRecord inTask, String reason, boolean validateIncomingUser, + PendingIntentRecord originatingPendingIntent) { userId = checkTargetUser(userId, validateIncomingUser, realCallingPid, realCallingUid, reason); @@ -267,6 +268,7 @@ public class ActivityStartController { .setActivityOptions(options) .setMayWait(userId) .setInTask(inTask) + .setOriginatingPendingIntent(originatingPendingIntent) .execute(); } @@ -278,10 +280,12 @@ public class ActivityStartController { * @param intents Intents to start. * @param userId Start the intents on this user. * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID. + * @param originatingPendingIntent PendingIntentRecord that originated this activity start or + * null if not originated by PendingIntent */ final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, - boolean validateIncomingUser) { + boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent) { final String reason = "startActivityInPackage"; @@ -290,12 +294,12 @@ public class ActivityStartController { // TODO: Switch to user app stacks here. return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options, - userId, reason); + userId, reason, originatingPendingIntent); } int startActivities(IApplicationThread caller, int callingUid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, - int userId, String reason) { + int userId, String reason, PendingIntentRecord originatingPendingIntent) { if (intents == null) { throw new NullPointerException("intents is null"); } @@ -374,6 +378,7 @@ public class ActivityStartController { // Top activity decides on animation being run, so we allow only for the // top one as otherwise an activity below might consume it. .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/) + .setOriginatingPendingIntent(originatingPendingIntent) .execute(); if (res < 0) { diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 73e3d33073fc..00ba3a61d1d6 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -99,6 +99,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; +import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; @@ -313,6 +314,7 @@ class ActivityStarter { int userId; WaitResult waitResult; int filterCallingUid; + PendingIntentRecord originatingPendingIntent; /** * If set to {@code true}, allows this activity start to look into @@ -369,6 +371,7 @@ class ActivityStarter { avoidMoveToFront = false; allowPendingRemoteAnimationRegistryLookup = true; filterCallingUid = UserHandle.USER_NULL; + originatingPendingIntent = null; } /** @@ -407,6 +410,7 @@ class ActivityStarter { allowPendingRemoteAnimationRegistryLookup = request.allowPendingRemoteAnimationRegistryLookup; filterCallingUid = request.filterCallingUid; + originatingPendingIntent = request.originatingPendingIntent; } } @@ -490,7 +494,8 @@ class ActivityStarter { mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId, mRequest.inTask, mRequest.reason, - mRequest.allowPendingRemoteAnimationRegistryLookup); + mRequest.allowPendingRemoteAnimationRegistryLookup, + mRequest.originatingPendingIntent); } else { return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent, mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo, @@ -500,7 +505,8 @@ class ActivityStarter { mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.componentSpecified, mRequest.outActivity, mRequest.inTask, mRequest.reason, - mRequest.allowPendingRemoteAnimationRegistryLookup); + mRequest.allowPendingRemoteAnimationRegistryLookup, + mRequest.originatingPendingIntent); } } finally { onExecutionComplete(); @@ -532,7 +538,8 @@ class ActivityStarter { String callingPackage, int realCallingPid, int realCallingUid, int startFlags, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, String reason, - boolean allowPendingRemoteAnimationRegistryLookup) { + boolean allowPendingRemoteAnimationRegistryLookup, + PendingIntentRecord originatingPendingIntent) { if (TextUtils.isEmpty(reason)) { throw new IllegalArgumentException("Need to specify a reason."); @@ -545,7 +552,7 @@ class ActivityStarter { aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord, - inTask, allowPendingRemoteAnimationRegistryLookup); + inTask, allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent); if (outActivity != null) { // mLastStartActivityRecord[0] is set in the call to startActivity above. @@ -575,7 +582,8 @@ class ActivityStarter { String callingPackage, int realCallingPid, int realCallingUid, int startFlags, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, - TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) { + TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup, + PendingIntentRecord originatingPendingIntent) { int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle @@ -865,10 +873,58 @@ class ActivityStarter { mController.doPendingActivityLaunches(false); + maybeLogActivityStart(callingUid, callingPackage, realCallingUid, intent, callerApp, r, + originatingPendingIntent); + return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, outActivity); } + private void maybeLogActivityStart(int callingUid, String callingPackage, int realCallingUid, + Intent intent, ProcessRecord callerApp, ActivityRecord r, + PendingIntentRecord originatingPendingIntent) { + boolean callerAppHasForegroundActivity = (callerApp != null) + ? callerApp.foregroundActivities + : false; + if (!mService.isActivityStartsLoggingEnabled() || callerAppHasForegroundActivity + || r == null) { + // skip logging in this case + return; + } + + try { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "logActivityStart"); + final int callingUidProcState = mService.getUidStateLocked(callingUid); + final boolean callingUidHasAnyVisibleWindow = + mService.mWindowManager.isAnyWindowVisibleForUid(callingUid); + final int realCallingUidProcState = (callingUid == realCallingUid) + ? callingUidProcState + : mService.getUidStateLocked(realCallingUid); + final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid) + ? callingUidHasAnyVisibleWindow + : mService.mWindowManager.isAnyWindowVisibleForUid(realCallingUid); + final String targetPackage = r.packageName; + final int targetUid = (r.appInfo != null) ? r.appInfo.uid : -1; + final int targetUidProcState = mService.getUidStateLocked(targetUid); + final boolean targetUidHasAnyVisibleWindow = (targetUid != -1) + ? mService.mWindowManager.isAnyWindowVisibleForUid(targetUid) + : false; + final String targetWhitelistTag = (targetUid != -1) + ? mService.getPendingTempWhitelistTagForUidLocked(targetUid) + : null; + + mSupervisor.getActivityMetricsLogger().logActivityStart(intent, callerApp, r, + callingUid, callingPackage, callingUidProcState, + callingUidHasAnyVisibleWindow, + realCallingUid, realCallingUidProcState, + realCallingUidHasAnyVisibleWindow, + targetUid, targetPackage, targetUidProcState, + targetUidHasAnyVisibleWindow, targetWhitelistTag, + (originatingPendingIntent != null)); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + } + } /** * Creates a launch intent for the given auxiliary resolution data. @@ -949,7 +1005,8 @@ class ActivityStarter { ProfilerInfo profilerInfo, WaitResult outResult, Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity, int userId, TaskRecord inTask, String reason, - boolean allowPendingRemoteAnimationRegistryLookup) { + boolean allowPendingRemoteAnimationRegistryLookup, + PendingIntentRecord originatingPendingIntent) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -1100,7 +1157,7 @@ class ActivityStarter { voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason, - allowPendingRemoteAnimationRegistryLookup); + allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent); Binder.restoreCallingIdentity(origId); @@ -2625,6 +2682,11 @@ class ActivityStarter { return this; } + ActivityStarter setOriginatingPendingIntent(PendingIntentRecord originatingPendingIntent) { + mRequest.originatingPendingIntent = originatingPendingIntent; + return this; + } + void dump(PrintWriter pw, String prefix) { prefix = prefix + " "; pw.print(prefix); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index a6dafbb1db36..f0e2876b4761 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -484,7 +484,8 @@ class AppErrors { task.intent, null, null, null, 0, 0, new SafeActivityOptions(ActivityOptions.makeBasic()), task.userId, null, - "AppErrors", false /*validateIncomingUser*/); + "AppErrors", false /*validateIncomingUser*/, + null /* originatingPendingIntent */); } } } diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index e0aa2a261b3c..4e00304a9da6 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -307,7 +307,7 @@ final class PendingIntentRecord extends IIntentSender.Stub { } else if (finalIntent.getComponent() != null) { finalIntent.getComponent().appendShortString(tag); } else if (finalIntent.getData() != null) { - tag.append(finalIntent.getData()); + tag.append(finalIntent.getData().toSafeString()); } owner.tempWhitelistForPendingIntentLocked(callingPid, callingUid, uid, duration, tag.toString()); @@ -346,13 +346,15 @@ final class PendingIntentRecord extends IIntentSender.Stub { res = owner.getActivityStartController().startActivitiesInPackage( uid, key.packageName, allIntents, allResolvedTypes, resultTo, mergedOptions, userId, - false /* validateIncomingUser */); + false /* validateIncomingUser */, + this /* originatingPendingIntent */); } else { res = owner.getActivityStartController().startActivityInPackage(uid, callingPid, callingUid, key.packageName, finalIntent, resolvedType, resultTo, resultWho, requestCode, 0, mergedOptions, userId, null, "PendingIntentRecord", - false /* validateIncomingUser */); + false /* validateIncomingUser */, + this /* originatingPendingIntent */); } } catch (RuntimeException e) { Slog.w(TAG, "Unable to send startActivity intent", e); diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index caf52e359548..28ebbb87f261 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -856,4 +856,8 @@ final class ProcessRecord { } return list; } + + boolean hasForegroundServices() { + return foregroundServices; + } } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index aba75ddb4555..90acda0a1c18 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -940,7 +940,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getIfaceStats(String iface, int type) { - return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + // eBPF code doesn't provide per-interface TCP counters. Use xt_qtaguid for now. + // TODO: delete getMobileTcp(Rx|Tx)Packets entirely. See b/110443385 . + if (type == TYPE_TCP_TX_PACKETS || type == TYPE_TCP_RX_PACKETS) { + return nativeGetIfaceStat(iface, type, false); + } else { + return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + } } @Override diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index c0fbfbb20b95..18f4bc768632 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -150,6 +150,7 @@ public class ConditionProviders extends ManagedServices { try { provider.onConnected(); } catch (RemoteException e) { + Slog.e(TAG, "can't connect to service " + info, e); // we tried } if (mCallback != null) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 1284468947c2..c6e71e53d595 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2122,6 +2122,10 @@ public class NotificationManagerService extends SystemService { enforceSystemOrSystemUI("setNotificationsEnabledForPackage"); mRankingHelper.setEnabled(pkg, uid, enabled); + mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_BAN_APP_NOTES) + .setType(MetricsEvent.TYPE_ACTION) + .setPackageName(pkg) + .setSubtype(enabled ? 1 : 0)); // Now, cancel any outstanding notifications that are part of a just-disabled app if (!enabled) { cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true, diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java index 67608753a2c3..b016fafa3d29 100644 --- a/services/core/java/com/android/server/notification/ZenLog.java +++ b/services/core/java/com/android/server/notification/ZenLog.java @@ -36,7 +36,8 @@ import java.util.List; public class ZenLog { private static final String TAG = "ZenLog"; - private static final boolean DEBUG = Build.IS_DEBUGGABLE; + // the ZenLog is *very* verbose, so be careful about setting this to true + private static final boolean DEBUG = false; private static final int SIZE = Build.IS_DEBUGGABLE ? 100 : 20; diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java index 63c0bafe389d..8013f7a099b6 100644 --- a/services/core/java/com/android/server/notification/ZenModeConditions.java +++ b/services/core/java/com/android/server/notification/ZenModeConditions.java @@ -59,7 +59,8 @@ public class ZenModeConditions implements ConditionProviders.Callback { pw.print(prefix); pw.print("mSubscriptions="); pw.println(mSubscriptions); } - public void evaluateConfig(ZenModeConfig config, boolean processSubscriptions) { + public void evaluateConfig(ZenModeConfig config, ComponentName trigger, + boolean processSubscriptions) { if (config == null) return; if (config.manualRule != null && config.manualRule.condition != null && !config.manualRule.isTrueOrUnknown()) { @@ -67,9 +68,9 @@ public class ZenModeConditions implements ConditionProviders.Callback { config.manualRule = null; } final ArraySet<Uri> current = new ArraySet<>(); - evaluateRule(config.manualRule, current, processSubscriptions); + evaluateRule(config.manualRule, current, null, processSubscriptions); for (ZenRule automaticRule : config.automaticRules.values()) { - evaluateRule(automaticRule, current, processSubscriptions); + evaluateRule(automaticRule, current, trigger, processSubscriptions); updateSnoozing(automaticRule); } @@ -102,7 +103,7 @@ public class ZenModeConditions implements ConditionProviders.Callback { @Override public void onServiceAdded(ComponentName component) { if (DEBUG) Log.d(TAG, "onServiceAdded " + component); - mHelper.setConfig(mHelper.getConfig(), "zmc.onServiceAdded"); + mHelper.setConfig(mHelper.getConfig(), component, "zmc.onServiceAdded"); } @Override @@ -110,17 +111,22 @@ public class ZenModeConditions implements ConditionProviders.Callback { if (DEBUG) Log.d(TAG, "onConditionChanged " + id + " " + condition); ZenModeConfig config = mHelper.getConfig(); if (config == null) return; + ComponentName trigger = null; boolean updated = updateCondition(id, condition, config.manualRule); for (ZenRule automaticRule : config.automaticRules.values()) { updated |= updateCondition(id, condition, automaticRule); updated |= updateSnoozing(automaticRule); + if (updated) { + trigger = automaticRule.component; + } } if (updated) { - mHelper.setConfig(config, "conditionChanged"); + mHelper.setConfig(config, trigger, "conditionChanged"); } } - private void evaluateRule(ZenRule rule, ArraySet<Uri> current, boolean processSubscriptions) { + private void evaluateRule(ZenRule rule, ArraySet<Uri> current, ComponentName trigger, + boolean processSubscriptions) { if (rule == null || rule.conditionId == null) return; final Uri id = rule.conditionId; boolean isSystemCondition = false; @@ -146,7 +152,8 @@ public class ZenModeConditions implements ConditionProviders.Callback { if (current != null) { current.add(id); } - if (processSubscriptions) { + if (processSubscriptions && trigger != null && trigger.equals(rule.component)) { + if (DEBUG) Log.d(TAG, "Subscribing to " + rule.component); if (mConditionProviders.subscribeIfNecessary(rule.component, rule.conditionId)) { synchronized (mSubscriptions) { mSubscriptions.put(rule.conditionId, rule.component); diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 669d5565534d..6ab2c43fb9ba 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -225,7 +225,7 @@ public class ZenModeHelper { config.user = user; } synchronized (mConfig) { - setConfigLocked(config, reason); + setConfigLocked(config, null, reason); } cleanUpZenRules(); } @@ -312,7 +312,7 @@ public class ZenModeHelper { ZenRule rule = new ZenRule(); populateZenRule(automaticZenRule, rule, true); newConfig.automaticRules.put(rule.id, rule); - if (setConfigLocked(newConfig, reason, true)) { + if (setConfigLocked(newConfig, reason, rule.component, true)) { return rule.id; } else { throw new AndroidRuntimeException("Could not create rule"); @@ -342,7 +342,7 @@ public class ZenModeHelper { } populateZenRule(automaticZenRule, rule, false); newConfig.automaticRules.put(ruleId, rule); - return setConfigLocked(newConfig, reason, true); + return setConfigLocked(newConfig, reason, rule.component, true); } } @@ -360,7 +360,7 @@ public class ZenModeHelper { throw new SecurityException( "Cannot delete rules not owned by your condition provider"); } - return setConfigLocked(newConfig, reason, true); + return setConfigLocked(newConfig, reason, null, true); } } @@ -376,7 +376,7 @@ public class ZenModeHelper { newConfig.automaticRules.removeAt(i); } } - return setConfigLocked(newConfig, reason, true); + return setConfigLocked(newConfig, reason, null, true); } } @@ -537,7 +537,7 @@ public class ZenModeHelper { newRule.enabler = caller; newConfig.manualRule = newRule; } - setConfigLocked(newConfig, reason, setRingerMode); + setConfigLocked(newConfig, reason, null, setRingerMode); } } @@ -644,7 +644,7 @@ public class ZenModeHelper { } if (DEBUG) Log.d(TAG, reason); synchronized (mConfig) { - setConfigLocked(config, reason); + setConfigLocked(config, null, reason); } } } @@ -673,7 +673,7 @@ public class ZenModeHelper { synchronized (mConfig) { final ZenModeConfig newConfig = mConfig.copy(); newConfig.applyNotificationPolicy(policy); - setConfigLocked(newConfig, "setNotificationPolicy"); + setConfigLocked(newConfig, null, "setNotificationPolicy"); } } @@ -697,7 +697,7 @@ public class ZenModeHelper { } } } - setConfigLocked(newConfig, "cleanUpZenRules"); + setConfigLocked(newConfig, null, "cleanUpZenRules"); } } @@ -710,17 +710,19 @@ public class ZenModeHelper { } } - public boolean setConfigLocked(ZenModeConfig config, String reason) { - return setConfigLocked(config, reason, true /*setRingerMode*/); + public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, + String reason) { + return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/); } - public void setConfig(ZenModeConfig config, String reason) { + public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) { synchronized (mConfig) { - setConfigLocked(config, reason); + setConfigLocked(config, triggeringComponent, reason); } } - private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) { + private boolean setConfigLocked(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { final long identity = Binder.clearCallingIdentity(); try { if (config == null || !config.isValid()) { @@ -733,7 +735,8 @@ public class ZenModeHelper { if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user); return true; } - mConditions.evaluateConfig(config, false /*processSubscriptions*/); // may modify config + // may modify config + mConditions.evaluateConfig(config, null, false /*processSubscriptions*/); mConfigs.put(config.user, config); if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable()); ZenLog.traceConfig(reason, mConfig, config); @@ -746,7 +749,7 @@ public class ZenModeHelper { dispatchOnPolicyChanged(); } mConfig = config; - mHandler.postApplyConfig(config, reason, setRingerMode); + mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode); return true; } catch (SecurityException e) { Log.wtf(TAG, "Invalid rule in config", e); @@ -756,13 +759,14 @@ public class ZenModeHelper { } } - private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { + private void applyConfig(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { final String val = Integer.toString(config.hashCode()); Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val); if (!evaluateZenMode(reason, setRingerMode)) { applyRestrictions(); // evaluateZenMode will also apply restrictions if changed } - mConditions.evaluateConfig(config, true /*processSubscriptions*/); + mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/); } private int getZenModeSetting() { @@ -1260,13 +1264,16 @@ public class ZenModeHelper { private final class ConfigMessageData { public final ZenModeConfig config; + public ComponentName triggeringComponent; public final String reason; public final boolean setRingerMode; - ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) { + ConfigMessageData(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { this.config = config; this.reason = reason; this.setRingerMode = setRingerMode; + this.triggeringComponent = triggeringComponent; } } @@ -1286,9 +1293,10 @@ public class ZenModeHelper { sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS); } - private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { + private void postApplyConfig(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { sendMessage(obtainMessage(MSG_APPLY_CONFIG, - new ConfigMessageData(config, reason, setRingerMode))); + new ConfigMessageData(config, reason, triggeringComponent, setRingerMode))); } @Override @@ -1303,7 +1311,7 @@ public class ZenModeHelper { case MSG_APPLY_CONFIG: ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj; applyConfig(applyConfigData.config, applyConfigData.reason, - applyConfigData.setRingerMode); + applyConfigData.triggeringComponent, applyConfigData.setRingerMode); } } } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index b0be4a9799bb..55b194078a69 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -34,6 +34,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.pm.Installer.InstallerException; +import com.android.server.pm.dex.ArtManagerService; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.DexoptUtils; @@ -289,7 +290,8 @@ public class PackageDexOptimizer { mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags, compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo, false /* downgrade*/, pkg.applicationInfo.targetSdkVersion, - profileName, dexMetadataPath, getReasonName(compilationReason)); + profileName, dexMetadataPath, + getAugmentedReasonName(compilationReason, dexMetadataPath != null)); if (packageStats != null) { long endTime = System.currentTimeMillis(); @@ -302,6 +304,12 @@ public class PackageDexOptimizer { } } + private String getAugmentedReasonName(int compilationReason, boolean useDexMetadata) { + String annotation = useDexMetadata + ? ArtManagerService.DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : ""; + return getReasonName(compilationReason) + annotation; + } + /** * Performs dexopt on the secondary dex {@code path} belonging to the app {@code info}. * diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 29047e756f71..dd83b19ea7ce 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -21952,9 +21952,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); //TODO: b/111402650 private void disableSkuSpecificApps() { - if (!mIsUpgrade && !mFirstBoot) { - return; - } String apkList[] = mContext.getResources().getStringArray( R.array.config_disableApksUnlessMatchedSku_apk_list); String skuArray[] = mContext.getResources().getStringArray( @@ -21968,7 +21965,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } for (String packageName : apkList) { setSystemAppHiddenUntilInstalled(packageName, true); - setSystemAppInstallState(packageName, false, ActivityManager.getCurrentUser()); + for (UserInfo user : sUserManager.getUsers(false)) { + setSystemAppInstallState(packageName, false, user.id); + } } } diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index 0ba78226a38f..21daa39e05e0 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -519,6 +519,11 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { private static final int TRON_COMPILATION_REASON_AB_OTA = 6; private static final int TRON_COMPILATION_REASON_INACTIVE = 7; private static final int TRON_COMPILATION_REASON_SHARED = 8; + private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA = 9; + + // The annotation to add as a suffix to the compilation reason when dexopt was + // performed with dex metadata. + public static final String DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION = "-dm"; /** * Convert the compilation reason to an int suitable to be logged to TRON. @@ -534,6 +539,10 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA; case "inactive" : return TRON_COMPILATION_REASON_INACTIVE; case "shared" : return TRON_COMPILATION_REASON_SHARED; + // This is a special marker for dex metadata installation that does not + // have an equivalent as a system property. + case "install" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : + return TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA; default: return TRON_COMPILATION_REASON_UNKNOWN; } } diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java index eca6f9f1ec47..14c985c090a3 100644 --- a/services/core/java/com/android/server/policy/BarController.java +++ b/services/core/java/com/android/server/policy/BarController.java @@ -196,7 +196,7 @@ public class BarController { } protected boolean skipAnimation() { - return false; + return !mWin.isDrawnLw(); } private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index dfb617999668..9a741bcfc3d6 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -76,6 +76,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CO import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; @@ -4397,17 +4398,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (isKeyguardShowingAndNotOccluded()) { // don't launch home if keyguard showing return; - } else if (mKeyguardOccluded && mKeyguardDelegate.isShowing()) { - mKeyguardDelegate.dismiss(new KeyguardDismissCallback() { - @Override - public void onDismissSucceeded() throws RemoteException { - mHandler.post(() -> { - startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); - }); - } - }, null /* message */); - return; - } else if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) { + } + + if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) { // when in keyguard restricted mode, must first verify unlock // before launching home mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() { @@ -4692,8 +4685,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { navTranslucent &= areTranslucentBarsAllowed(); } boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null - && mStatusBar.getAttrs().height == MATCH_PARENT - && mStatusBar.getAttrs().width == MATCH_PARENT; + && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0; // When the navigation bar isn't visible, we put up a fake input window to catch all // touch events. This way we can detect when the user presses anywhere to bring back the @@ -5696,7 +5688,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // Take note if a window wants to acquire a sleep token. - if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0 + if ((attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0 && win.canAcquireSleepToken()) { mWindowSleepTokenNeeded = true; } @@ -5752,9 +5744,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mStatusBarController.setShowTransparent(true /* transparent */); } - WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); - boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT - && statusBarAttrs.width == MATCH_PARENT; + boolean statusBarExpanded = + (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0; boolean topAppHidesStatusBar = topAppHidesStatusBar(); if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent || statusBarExpanded) { diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 44136661bee5..f9f4bbfc8eb0 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -46,7 +46,6 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; -import android.os.storage.StorageManager; import android.provider.Settings; import android.service.trust.TrustAgentService; import android.text.TextUtils; @@ -60,7 +59,6 @@ import android.view.IWindowManager; import android.view.WindowManagerGlobal; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; -import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.SystemService; @@ -431,13 +429,20 @@ public class TrustManagerService extends SystemService { for (int i = 0; i < userInfos.size(); i++) { UserInfo info = userInfos.get(i); - if (info == null || info.partial || !info.isEnabled() || info.guestToRemove - || !info.supportsSwitchToByUser()) { + if (info == null || info.partial || !info.isEnabled() || info.guestToRemove) { continue; } int id = info.id; boolean secure = mLockPatternUtils.isSecure(id); + + if (!info.supportsSwitchToByUser()) { + if (info.isManagedProfile() && !secure) { + setDeviceLockedForUser(id, false); + } + continue; + } + boolean trusted = aggregateIsTrusted(id); boolean showingKeyguard = true; boolean fingerprintAuthenticated = false; @@ -992,7 +997,8 @@ public class TrustManagerService extends SystemService { enforceReportPermission(); final long identity = Binder.clearCallingIdentity(); try { - if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) + && mLockPatternUtils.isSecure(userId)) { synchronized (mDeviceLockedForUser) { mDeviceLockedForUser.put(userId, locked); } diff --git a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java index f25ec5cd935e..bebc5656c284 100644 --- a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java +++ b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java @@ -75,12 +75,14 @@ public class ForcedSeamlessRotator { public void finish(WindowToken token, WindowState win) { mTransform.reset(); token.getPendingTransaction().setMatrix(token.mSurfaceControl, mTransform, mFloat9); - token.getPendingTransaction().deferTransactionUntil(token.mSurfaceControl, - win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), - win.getFrameNumber()); - win.getPendingTransaction().deferTransactionUntil(win.mSurfaceControl, - win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), - win.getFrameNumber()); + if (win.mWinAnimator.mSurfaceController != null) { + token.getPendingTransaction().deferTransactionUntil(token.mSurfaceControl, + win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), + win.getFrameNumber()); + win.getPendingTransaction().deferTransactionUntil(win.mSurfaceControl, + win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), + win.getFrameNumber()); + } } public void dump(PrintWriter pw) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8bc224636c1e..c4a0a6961136 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -6221,6 +6221,17 @@ public class WindowManagerService extends IWindowManager.Stub } /** + * Returns true if the callingUid has any window currently visible to the user. + */ + public boolean isAnyWindowVisibleForUid(int callingUid) { + synchronized (mWindowMap) { + return mRoot.forAllWindows(w -> { + return w.getOwningUid() == callingUid && w.isVisible(); + }, true /* traverseTopToBottom */); + } + } + + /** * Called when a task has been removed from the recent tasks list. * <p> * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java index 1520859d4aac..8d056fc4a8c0 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java @@ -53,6 +53,7 @@ import android.view.Gravity; import org.junit.runner.RunWith; import org.junit.Test; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED; import static com.android.server.am.ActivityManagerService.ANIMATE; @@ -62,11 +63,13 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyObject; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.times; @@ -91,6 +94,7 @@ public class ActivityStarterTests extends ActivityTestsBase { private ActivityManagerService mService; private ActivityStarter mStarter; private ActivityStartController mController; + private ActivityMetricsLogger mActivityMetricsLogger; private static final int PRECONDITION_NO_CALLER_APP = 1; private static final int PRECONDITION_NO_INTENT_COMPONENT = 1 << 1; @@ -104,11 +108,17 @@ public class ActivityStarterTests extends ActivityTestsBase { private static final int PRECONDITION_CANNOT_START_ANY_ACTIVITY = 1 << 9; private static final int PRECONDITION_DISALLOW_APP_SWITCHING = 1 << 10; + private static final int FAKE_CALLING_UID = 666; + private static final int FAKE_REAL_CALLING_UID = 667; + private static final String FAKE_CALLING_PACKAGE = "com.whatever.dude"; + @Override public void setUp() throws Exception { super.setUp(); mService = createActivityManagerService(); mController = mock(ActivityStartController.class); + mActivityMetricsLogger = mock(ActivityMetricsLogger.class); + clearInvocations(mActivityMetricsLogger); mStarter = new ActivityStarter(mController, mService, mService.mStackSupervisor, mock(ActivityStartInterceptor.class)); } @@ -471,4 +481,46 @@ public class ActivityStarterTests extends ActivityTestsBase { assertTrue(stack.getAllTasks().isEmpty()); } } + + /** + * This test ensures that activity starts are not being logged when the logging is disabled. + */ + @Test + public void testActivityStartsLogging_noLoggingWhenDisabled() { + doReturn(false).when(mService).isActivityStartsLoggingEnabled(); + doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger(); + + ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK); + starter.setReason("testActivityStartsLogging_noLoggingWhenDisabled").execute(); + + // verify logging wasn't done + verify(mActivityMetricsLogger, never()).logActivityStart(any(), any(), any(), anyInt(), + any(), anyInt(), anyBoolean(), anyInt(), anyInt(), anyBoolean(), anyInt(), any(), + anyInt(), anyBoolean(), any(), anyBoolean()); + } + + /** + * This test ensures that activity starts are being logged when the logging is enabled. + */ + @Test + public void testActivityStartsLogging_logsWhenEnabled() { + // note: conveniently this package doesn't have any activity visible + doReturn(true).when(mService).isActivityStartsLoggingEnabled(); + doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger(); + + ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK) + .setCallingUid(FAKE_CALLING_UID) + .setRealCallingUid(FAKE_REAL_CALLING_UID) + .setCallingPackage(FAKE_CALLING_PACKAGE) + .setOriginatingPendingIntent(null); + + starter.setReason("testActivityStartsLogging_logsWhenEnabled").execute(); + + // verify the above activity start was logged + verify(mActivityMetricsLogger, times(1)).logActivityStart(any(), any(), any(), + eq(FAKE_CALLING_UID), eq(FAKE_CALLING_PACKAGE), anyInt(), anyBoolean(), + eq(FAKE_REAL_CALLING_UID), anyInt(), anyBoolean(), anyInt(), + eq(ActivityBuilder.getDefaultComponent().getPackageName()), anyInt(), anyBoolean(), + any(), eq(false)); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index afc12636007f..63a60a470488 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -116,7 +116,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelperSpy.writeXml(serializer, forBackup, version); serializer.endDocument(); serializer.flush(); - mZenModeHelperSpy.setConfig(new ZenModeConfig(), "writing xml"); + mZenModeHelperSpy.setConfig(new ZenModeConfig(), null, "writing xml"); return baos; } diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index bb3af3cd1687..52f7a6042095 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -948,16 +948,15 @@ public class WifiEnterpriseConfig implements Parcelable { * for Hotspot 2.0 defined matching of AAA server certs per WFA HS2.0 spec, section 7.3.3.2, * second paragraph. * - * From wpa_supplicant documentation: - * Constraint for server domain name. If set, this FQDN is used as a suffix match requirement + * <p>From wpa_supplicant documentation: + * <p>Constraint for server domain name. If set, this FQDN is used as a suffix match requirement * for the AAAserver certificate in SubjectAltName dNSName element(s). If a matching dNSName is - * found, this constraint is met. If no dNSName values are present, this constraint is matched - * against SubjectName CN using same suffix match comparison. - * Suffix match here means that the host/domain name is compared one label at a time starting + * found, this constraint is met. + * <p>Suffix match here means that the host/domain name is compared one label at a time starting * from the top-level domain and all the labels in domain_suffix_match shall be included in the * certificate. The certificate may include additional sub-level labels in addition to the * required labels. - * For example, domain_suffix_match=example.com would match test.example.com but would not + * <p>For example, domain_suffix_match=example.com would match test.example.com but would not * match test-example.com. * @param domain The domain value */ |