diff options
Diffstat (limited to 'core/java/android')
44 files changed, 918 insertions, 449 deletions
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 223d528..48e380b 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -726,6 +726,16 @@ public class AppOpsManager { false }; + /** + * This is a mapping from a permission name to public app op name. + */ + private static final ArrayMap<String, String> sPermToOp = new ArrayMap<>(); + static { + sPermToOp.put(Manifest.permission.ACCESS_COARSE_LOCATION, OPSTR_COARSE_LOCATION); + sPermToOp.put(Manifest.permission.ACCESS_FINE_LOCATION, OPSTR_FINE_LOCATION); + sPermToOp.put(Manifest.permission.PACKAGE_USAGE_STATS, OPSTR_GET_USAGE_STATS); + } + private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>(); static { @@ -1066,6 +1076,21 @@ public class AppOpsManager { } /** + * Gets the app op name associated with a given permission. + * The app op name is one of the public constants defined + * in this class such as {@link #OPSTR_COARSE_LOCATION}. + * + * @param permission The permission. + * @return The app op associated with the permission or null. + * + * @hide + */ + @SystemApi + public static String permissionToOp(String permission) { + return sPermToOp.get(permission); + } + + /** * Monitor for changes to the operating mode for the given op in the given app package. * @param op The operation to monitor, one of OPSTR_*. * @param packageName The name of the application to monitor. diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 16a2430..6e511f3 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -79,6 +79,7 @@ import android.view.Display; import dalvik.system.VMRuntime; import com.android.internal.annotations.GuardedBy; +import com.android.internal.os.SomeArgs; import com.android.internal.util.Preconditions; import com.android.internal.util.UserIcons; @@ -2054,8 +2055,7 @@ final class ApplicationPackageManager extends PackageManager { /** {@hide} */ private static class MoveCallbackDelegate extends IPackageMoveObserver.Stub implements Handler.Callback { - private static final int MSG_STARTED = 1; - private static final int MSG_STATUS_CHANGED = 2; + private static final int MSG_STATUS_CHANGED = 1; final MoveCallback mCallback; final Handler mHandler; @@ -2067,26 +2067,25 @@ final class ApplicationPackageManager extends PackageManager { @Override public boolean handleMessage(Message msg) { - final int moveId = msg.arg1; switch (msg.what) { - case MSG_STARTED: - mCallback.onStarted(moveId, (String) msg.obj); - return true; case MSG_STATUS_CHANGED: - mCallback.onStatusChanged(moveId, msg.arg2, (long) msg.obj); + final SomeArgs args = (SomeArgs) msg.obj; + mCallback.onStatusChanged(args.argi1, (String) args.arg2, args.argi3, + (long) args.arg4); + args.recycle(); return true; } return false; } @Override - public void onStarted(int moveId, String title) { - mHandler.obtainMessage(MSG_STARTED, moveId, 0, title).sendToTarget(); - } - - @Override - public void onStatusChanged(int moveId, int status, long estMillis) { - mHandler.obtainMessage(MSG_STATUS_CHANGED, moveId, status, estMillis).sendToTarget(); + public void onStatusChanged(int moveId, String moveTitle, int status, long estMillis) { + final SomeArgs args = SomeArgs.obtain(); + args.argi1 = moveId; + args.arg2 = moveTitle; + args.argi3 = status; + args.arg4 = estMillis; + mHandler.obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget(); } } diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index ebb3c43..2c12317 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -199,9 +199,12 @@ public class KeyguardManager { } /** - * Return whether the keyguard requires a password to unlock. + * Return whether the keyguard is secured by a PIN, pattern or password or a SIM card + * is currently locked. * - * @return true if keyguard is secure. + * <p>See also {@link #isDeviceSecure()} which ignores SIM locked states. + * + * @return true if a PIN, pattern or password is set or a SIM card is locked. */ public boolean isKeyguardSecure() { try { @@ -240,12 +243,8 @@ public class KeyguardManager { } /** - * Returns whether the device is currently locked and requires a PIN, pattern or - * password to unlock. + * Per-user version of {@link #isDeviceLocked()}. * - * @param userId the user for which the locked state should be reported. - * @return true if unlocking the device currently requires a PIN, pattern or - * password. * @hide */ public boolean isDeviceLocked(int userId) { @@ -260,6 +259,8 @@ public class KeyguardManager { * Returns whether the device is secured with a PIN, pattern or * password. * + * <p>See also {@link #isKeyguardSecure} which treats SIM locked states as secure. + * * @return true if a PIN, pattern or password was set. */ public boolean isDeviceSecure() { @@ -267,11 +268,8 @@ public class KeyguardManager { } /** - * Returns whether the device is secured with a PIN, pattern or - * password. + * Per-user version of {@link #isDeviceSecure()}. * - * @param userId the user for which the secure state should be reported. - * @return true if a PIN, pattern or password was set. * @hide */ public boolean isDeviceSecure(int userId) { diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 207519c..31d1ab7 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -63,12 +63,20 @@ public class StatusBarManager { | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK | DISABLE_SEARCH; + /** + * Flag to disable quick settings. + * + * Setting this flag disables quick settings completely, but does not disable expanding the + * notification shade. + */ + public static final int DISABLE2_QUICK_SETTINGS = 0x00000001; + public static final int DISABLE2_NONE = 0x00000000; - public static final int DISABLE2_MASK = 0x00000000; + public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS; @IntDef(flag = true, - value = {DISABLE2_NONE, DISABLE2_MASK}) + value = {DISABLE2_NONE, DISABLE2_MASK, DISABLE2_QUICK_SETTINGS}) @Retention(RetentionPolicy.SOURCE) public @interface Disable2Flags {} diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index ed814c3..cf9813f 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -807,6 +807,24 @@ public class DevicePolicyManager { public static final String ACTION_SYSTEM_UPDATE_POLICY_CHANGED = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED"; + /** + * Permission policy to prompt user for new permission requests for runtime permissions. + * Already granted or denied permissions are not affected by this. + */ + public static final int PERMISSION_POLICY_PROMPT = 0; + + /** + * Permission policy to always grant new permission requests for runtime permissions. + * Already granted or denied permissions are not affected by this. + */ + public static final int PERMISSION_POLICY_AUTO_GRANT = 1; + + /** + * Permission policy to always deny new permission requests for runtime permissions. + * Already granted or denied permissions are not affected by this. + */ + public static final int PERMISSION_POLICY_AUTO_DENY = 2; + /** * Return true if the given administrator component is currently @@ -4342,4 +4360,58 @@ public class DevicePolicyManager { Log.w(TAG, "Failed talking with device policy service", re); } } + + /** + * Called by profile or device owners to set the default response for future runtime permission + * requests by applications. The policy can allow for normal operation which prompts the + * user to grant a permission, or can allow automatic granting or denying of runtime + * permission requests by an application. This also applies to new permissions declared by app + * updates. + * @param admin Which profile or device owner this request is associated with. + * @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT}, + * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}. + */ + public void setPermissionPolicy(ComponentName admin, int policy) { + try { + mService.setPermissionPolicy(admin, policy); + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } + } + + /** + * Returns the current runtime permission policy set by the device or profile owner. The + * default is {@link #PERMISSION_POLICY_PROMPT}. + * @param admin Which profile or device owner this request is associated with. + * @return the current policy for future permission requests. + */ + public int getPermissionPolicy(ComponentName admin) { + try { + return mService.getPermissionPolicy(admin); + } catch (RemoteException re) { + return PERMISSION_POLICY_PROMPT; + } + } + + /** + * Grants or revokes a runtime permission to a specific application so that the user + * does not have to be prompted. This might affect all permissions in a group that the + * runtime permission belongs to. This method can only be called by a profile or device + * owner. + * @param admin Which profile or device owner this request is associated with. + * @param packageName The application to grant or revoke a permission to. + * @param permission The permission to grant or revoke. + * @param granted Whether or not to grant the permission. If false, all permissions in the + * associated permission group will be denied. + * @return whether the permission was successfully granted or revoked + */ + public boolean setPermissionGranted(ComponentName admin, String packageName, + String permission, boolean granted) { + try { + return mService.setPermissionGranted(admin, packageName, permission, granted); + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + return false; + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index a678c51..833bc00 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -229,4 +229,9 @@ interface IDevicePolicyManager { boolean getDoNotAskCredentialsOnBoot(); void notifyPendingSystemUpdate(in long updateReceivedTime); + + void setPermissionPolicy(in ComponentName admin, int policy); + int getPermissionPolicy(in ComponentName admin); + boolean setPermissionGranted(in ComponentName admin, String packageName, String permission, + boolean granted); } diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index f2e7fc4..4769bd0 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -593,7 +593,8 @@ final class ContentProviderProxy implements IContentProvider DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply); int has = reply.readInt(); - ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null; + ParcelFileDescriptor fd = has != 0 ? ParcelFileDescriptor.CREATOR + .createFromParcel(reply) : null; return fd; } finally { data.recycle(); diff --git a/core/java/android/content/pm/IPackageMoveObserver.aidl b/core/java/android/content/pm/IPackageMoveObserver.aidl index 50ab3b5..155ed0b 100644 --- a/core/java/android/content/pm/IPackageMoveObserver.aidl +++ b/core/java/android/content/pm/IPackageMoveObserver.aidl @@ -22,6 +22,5 @@ package android.content.pm; * @hide */ oneway interface IPackageMoveObserver { - void onStarted(int moveId, String title); - void onStatusChanged(int moveId, int status, long estMillis); + void onStatusChanged(int moveId, String moveTitle, int status, long estMillis); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e1c271d..a1ee7fc 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -209,7 +209,14 @@ public abstract class PackageManager { * matching. This is a synonym for including the CATEGORY_DEFAULT in your * supplied Intent. */ - public static final int MATCH_DEFAULT_ONLY = 0x00010000; + public static final int MATCH_DEFAULT_ONLY = 0x00010000; + + /** + * Querying flag: if set and if the platform is doing any filtering of the results, then + * the filtering will not happen. This is a synonym for saying that all results should + * be returned. + */ + public static final int MATCH_ALL = 0x00020000; /** * Flag for {@link addCrossProfileIntentFilter}: if this flag is set: @@ -2637,6 +2644,8 @@ public abstract class PackageManager { * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}. * + * You can also set {@link #MATCH_ALL} for preventing the filtering of the results. + * * @return A List<ResolveInfo> containing one entry for each matching * Activity. These are ordered from best to worst match -- that * is, the first item in the list is what is returned by @@ -2658,6 +2667,8 @@ public abstract class PackageManager { * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}. * + * You can also set {@link #MATCH_ALL} for preventing the filtering of the results. + * * @return A List<ResolveInfo> containing one entry for each matching * Activity. These are ordered from best to worst match -- that * is, the first item in the list is what is returned by @@ -4201,8 +4212,8 @@ public abstract class PackageManager { /** {@hide} */ public static abstract class MoveCallback { - public abstract void onStarted(int moveId, String title); - public abstract void onStatusChanged(int moveId, int status, long estMillis); + public abstract void onStatusChanged(int moveId, String moveTitle, int status, + long estMillis); } /** {@hide} */ diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 87a1ca9..19e821c 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -603,10 +603,9 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>List of available high speed video size and fps range configurations * supported by the camera device, in the format of (width, height, fps_min, fps_max).</p> - * <p>When HIGH_SPEED_VIDEO is supported in {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}, - * this metadata will list the supported high speed video size and fps range - * configurations. All the sizes listed in this configuration will be a subset - * of the sizes reported by StreamConfigurationMap#getOutputSizes for processed + * <p>When HIGH_SPEED_VIDEO is supported in {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}, this metadata + * will list the supported high speed video size and fps range configurations. All the sizes + * listed in this configuration will be a subset of the sizes reported by {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } for processed * non-stalling formats.</p> * <p>For the high speed video use case, where the application will set * {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} to HIGH_SPEED_VIDEO in capture requests, the application must @@ -1116,11 +1115,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * into the 3 stream types as below:</p> * <ul> * <li>Processed (but stalling): any non-RAW format with a stallDurations > 0. - * Typically JPEG format (ImageFormat#JPEG).</li> - * <li>Raw formats: ImageFormat#RAW_SENSOR, ImageFormat#RAW10, ImageFormat#RAW12, - * and ImageFormat#RAW_OPAQUE.</li> + * Typically {@link android.graphics.ImageFormat#JPEG JPEG format}.</li> + * <li>Raw formats: {@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}, {@link android.graphics.ImageFormat#RAW10 RAW10}, or {@link android.graphics.ImageFormat#RAW12 RAW12}.</li> * <li>Processed (but not-stalling): any non-RAW format without a stall duration. - * Typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12.</li> + * Typically {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}, + * {@link android.graphics.ImageFormat#NV21 NV21}, or + * {@link android.graphics.ImageFormat#YV12 YV12}.</li> * </ul> * <p><b>Range of valid values:</b><br></p> * <p>For processed (and stalling) format streams, >= 1.</p> @@ -1148,10 +1148,9 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * be any <code>RAW</code> and supported format provided by {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}.</p> * <p>In particular, a <code>RAW</code> format is typically one of:</p> * <ul> - * <li>ImageFormat#RAW_SENSOR</li> - * <li>ImageFormat#RAW10</li> - * <li>ImageFormat#RAW12</li> - * <li>Opaque <code>RAW</code></li> + * <li>{@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}</li> + * <li>{@link android.graphics.ImageFormat#RAW10 RAW10}</li> + * <li>{@link android.graphics.ImageFormat#RAW12 RAW12}</li> * </ul> * <p>LEGACY mode devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> LEGACY) * never support raw streams.</p> @@ -1180,13 +1179,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>Processed (but not-stalling) is defined as any non-RAW format without a stall duration. * Typically:</p> * <ul> - * <li>ImageFormat#YUV_420_888</li> - * <li>ImageFormat#NV21</li> - * <li>ImageFormat#YV12</li> - * <li>Implementation-defined formats, i.e. StreamConfiguration#isOutputSupportedFor(Class)</li> + * <li>{@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}</li> + * <li>{@link android.graphics.ImageFormat#NV21 NV21}</li> + * <li>{@link android.graphics.ImageFormat#YV12 YV12}</li> + * <li>Implementation-defined formats, i.e. {@link android.hardware.camera2.params.StreamConfigurationMap#isOutputSupportedFor(Class) }</li> * </ul> - * <p>For full guarantees, query StreamConfigurationMap#getOutputStallDuration with - * a processed format -- it will return 0 for a non-stalling stream.</p> + * <p>For full guarantees, query {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } with a + * processed format -- it will return 0 for a non-stalling stream.</p> * <p>LEGACY devices will support at least 2 processing/non-stalling streams.</p> * <p><b>Range of valid values:</b><br></p> * <p>>= 3 @@ -1212,10 +1211,11 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * the camera device. Using more streams simultaneously may require more hardware and * CPU resources that will consume more power. The image format for this kind of an output stream can * be any non-<code>RAW</code> and supported format provided by {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}.</p> - * <p>A processed and stalling format is defined as any non-RAW format with a stallDurations > 0. - * Typically only the <code>JPEG</code> format (ImageFormat#JPEG) is a stalling format.</p> - * <p>For full guarantees, query StreamConfigurationMap#getOutputStallDuration with - * a processed format -- it will return a non-0 value for a stalling stream.</p> + * <p>A processed and stalling format is defined as any non-RAW format with a stallDurations + * > 0. Typically only the {@link android.graphics.ImageFormat#JPEG JPEG format} is a + * stalling format.</p> + * <p>For full guarantees, query {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } with a + * processed format -- it will return a non-0 value for a stalling stream.</p> * <p>LEGACY devices will support up to 1 processing/stalling stream.</p> * <p><b>Range of valid values:</b><br></p> * <p>>= 1</p> @@ -1232,10 +1232,9 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>The maximum numbers of any type of input streams * that can be configured and used simultaneously by a camera device.</p> * <p>When set to 0, it means no input stream is supported.</p> - * <p>The image format for a input stream can be any supported - * format returned by StreamConfigurationMap#getInputFormats. When using an - * input stream, there must be at least one output stream - * configured to to receive the reprocessed images.</p> + * <p>The image format for a input stream can be any supported format returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats }. When using an + * input stream, there must be at least one output stream configured to to receive the + * reprocessed images.</p> * <p>When an input stream and some output streams are used in a reprocessing request, * only the input buffer will be used to produce these output stream buffers, and a * new sensor image will not be captured.</p> @@ -1352,7 +1351,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>A list of all keys that the camera device has available - * to use with CaptureRequest.</p> + * to use with {@link android.hardware.camera2.CaptureRequest }.</p> * <p>Attempting to set a key into a CaptureRequest that is not * listed here will result in an invalid request and will be rejected * by the camera device.</p> @@ -1370,7 +1369,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>A list of all keys that the camera device has available - * to use with CaptureResult.</p> + * to use with {@link android.hardware.camera2.CaptureResult }.</p> * <p>Attempting to get a key from a CaptureResult that is not * listed here will always return a <code>null</code> value. Getting a key from * a CaptureResult that is listed here will generally never return a <code>null</code> @@ -1396,7 +1395,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>A list of all keys that the camera device has available - * to use with CameraCharacteristics.</p> + * to use with {@link android.hardware.camera2.CameraCharacteristics }.</p> * <p>This entry follows the same rules as * android.request.availableResultKeys (except that it applies for * CameraCharacteristics instead of CaptureResult). See above for more @@ -1535,34 +1534,31 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * </thead> * <tbody> * <tr> - * <td align="left">PRIVATE (ImageFormat#PRIVATE)</td> - * <td align="left">JPEG</td> + * <td align="left">{@link android.graphics.ImageFormat#PRIVATE }</td> + * <td align="left">{@link android.graphics.ImageFormat#JPEG }</td> * <td align="left">OPAQUE_REPROCESSING</td> * </tr> * <tr> - * <td align="left">PRIVATE</td> - * <td align="left">YUV_420_888</td> + * <td align="left">{@link android.graphics.ImageFormat#PRIVATE }</td> + * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td> * <td align="left">OPAQUE_REPROCESSING</td> * </tr> * <tr> - * <td align="left">YUV_420_888</td> - * <td align="left">JPEG</td> + * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td> + * <td align="left">{@link android.graphics.ImageFormat#JPEG }</td> * <td align="left">YUV_REPROCESSING</td> * </tr> * <tr> - * <td align="left">YUV_420_888</td> - * <td align="left">YUV_420_888</td> + * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td> + * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td> * <td align="left">YUV_REPROCESSING</td> * </tr> * </tbody> * </table> - * <p>PRIVATE refers to a device-internal format that is not directly application-visible. - * A PRIVATE input surface can be acquired by - * ImageReader.newOpaqueInstance(width, height, maxImages). - * For a OPAQUE_REPROCESSING-capable camera device, using the PRIVATE format - * as either input or output will never hurt maximum frame rate (i.e. - * StreamConfigurationMap#getOutputStallDuration(format, size) is always 0), - * where format is ImageFormat#PRIVATE.</p> + * <p>PRIVATE refers to a device-internal format that is not directly application-visible. A + * PRIVATE input surface can be acquired by {@link android.media.ImageReader#newOpaqueInstance }.</p> + * <p>For a OPAQUE_REPROCESSING-capable camera device, using the PRIVATE format as either input + * or output will never hurt maximum frame rate (i.e. {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration getOutputStallDuration(ImageFormat.PRIVATE, size)} is always 0),</p> * <p>Attempting to configure an input stream with output streams not * listed as available in this map is not valid.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> @@ -1680,7 +1676,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * android.scaler.availableStallDurations for more details about * calculating the max frame rate.</p> * <p>(Keep in sync with - * StreamConfigurationMap#getOutputMinFrameDuration)</p> + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration })</p> * <p><b>Units</b>: (format, width, height, ns) x n</p> * <p>This key is available on all devices.</p> * @@ -1692,7 +1688,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>This lists the maximum stall duration for each - * format/size combination.</p> + * output format/size combination.</p> * <p>A stall duration is how much extra time would get added * to the normal minimum frame duration for a repeating request * that has streams with non-zero stall.</p> @@ -1734,12 +1730,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * ignored).</p> * <p>The following formats may always have a stall duration:</p> * <ul> - * <li>ImageFormat#JPEG</li> - * <li>ImageFormat#RAW_SENSOR</li> + * <li>{@link android.graphics.ImageFormat#JPEG }</li> + * <li>{@link android.graphics.ImageFormat#RAW_SENSOR }</li> * </ul> * <p>The following formats will never have a stall duration:</p> * <ul> - * <li>ImageFormat#YUV_420_888</li> + * <li>{@link android.graphics.ImageFormat#YUV_420_888 }</li> + * <li>{@link android.graphics.ImageFormat#RAW10 }</li> * </ul> * <p>All other formats may or may not have an allowed stall duration on * a per-capability basis; refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} @@ -1747,7 +1744,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} for more information about * calculating the max frame rate (absent stalls).</p> * <p>(Keep up to date with - * StreamConfigurationMap#getOutputStallDuration(int, Size) )</p> + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } )</p> * <p><b>Units</b>: (format, width, height, ns) x n</p> * <p>This key is available on all devices.</p> * @@ -1786,57 +1783,57 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * </thead> * <tbody> * <tr> - * <td align="center">JPEG</td> + * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td> * <td align="center">{@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</td> * <td align="center">Any</td> * <td align="center"></td> * </tr> * <tr> - * <td align="center">JPEG</td> + * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td> * <td align="center">1920x1080 (1080p)</td> * <td align="center">Any</td> * <td align="center">if 1080p <= activeArraySize</td> * </tr> * <tr> - * <td align="center">JPEG</td> + * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td> * <td align="center">1280x720 (720)</td> * <td align="center">Any</td> * <td align="center">if 720p <= activeArraySize</td> * </tr> * <tr> - * <td align="center">JPEG</td> + * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td> * <td align="center">640x480 (480p)</td> * <td align="center">Any</td> * <td align="center">if 480p <= activeArraySize</td> * </tr> * <tr> - * <td align="center">JPEG</td> + * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td> * <td align="center">320x240 (240p)</td> * <td align="center">Any</td> * <td align="center">if 240p <= activeArraySize</td> * </tr> * <tr> - * <td align="center">YUV_420_888</td> + * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td> * <td align="center">all output sizes available for JPEG</td> * <td align="center">FULL</td> * <td align="center"></td> * </tr> * <tr> - * <td align="center">YUV_420_888</td> + * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td> * <td align="center">all output sizes available for JPEG, up to the maximum video size</td> * <td align="center">LIMITED</td> * <td align="center"></td> * </tr> * <tr> - * <td align="center">IMPLEMENTATION_DEFINED</td> + * <td align="center">{@link android.graphics.ImageFormat#PRIVATE }</td> * <td align="center">same as YUV_420_888</td> * <td align="center">Any</td> * <td align="center"></td> * </tr> * </tbody> * </table> - * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} for additional - * mandatory stream configurations on a per-capability basis.</p> + * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and {@link android.hardware.camera2.CameraDevice#createCaptureSession } for additional mandatory + * stream configurations on a per-capability basis.</p> * <p>This key is available on all devices.</p> * * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL @@ -1973,8 +1970,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>Attempting to use frame durations beyond the maximum will result in the frame * duration being clipped to the maximum. See that control for a full definition of frame * durations.</p> - * <p>Refer to StreamConfigurationMap#getOutputMinFrameDuration(int,Size) for the minimum - * frame duration values.</p> + * <p>Refer to {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration } + * for the minimum frame duration values.</p> * <p><b>Units</b>: Nanoseconds</p> * <p><b>Range of valid values:</b><br> * For FULL capability devices @@ -2634,6 +2631,41 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri new Key<Integer>("android.sync.maxLatency", int.class); /** + * <p>The maximal camera capture pipeline stall (in unit of frame count) introduced by a + * reprocess capture request.</p> + * <p>The key describes the maximal interference that one reprocess (input) request + * can introduce to the camera simultaneous streaming of regular (output) capture + * requests, including repeating requests.</p> + * <p>When a reprocessing capture request is submitted while a camera output repeating request + * (e.g. preview) is being served by the camera device, it may preempt the camera capture + * pipeline for at least one frame duration so that the camera device is unable to process + * the following capture request in time for the next sensor start of exposure boundary. + * When this happens, the application may observe a capture time gap (longer than one frame + * duration) between adjacent capture output frames, which usually exhibits as preview + * glitch if the repeating request output targets include a preview surface. This key gives + * the worst-case number of frame stall introduced by one reprocess request with any kind of + * formats/sizes combination.</p> + * <p>If this key reports 0, it means a reprocess request doesn't introduce any glitch to the + * ongoing camera repeating request outputs, as if this reprocess request is never issued.</p> + * <p>This key is supported if the camera device supports OPAQUE or YUV reprocessing ( + * i.e. {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains OPAQUE_REPROCESSING or + * YUV_REPROCESSING).</p> + * <p><b>Units</b>: Number of frames.</p> + * <p><b>Range of valid values:</b><br> + * <= 4</p> + * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> + * + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL + * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES + */ + @PublicKey + public static final Key<Integer> REPROCESS_MAX_CAPTURE_STALL = + new Key<Integer>("android.reprocess.maxCaptureStall", int.class); + + /** * <p>The available depth dataspace stream * configurations that this camera device supports * (i.e. format, width, height, output/input stream).</p> @@ -2672,8 +2704,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and * android.scaler.availableStallDurations for more details about * calculating the max frame rate.</p> - * <p>(Keep in sync with - * StreamConfigurationMap#getOutputMinFrameDuration)</p> + * <p>(Keep in sync with {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration })</p> * <p><b>Units</b>: (format, width, height, ns) x n</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - @@ -2689,7 +2720,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri /** * <p>This lists the maximum stall duration for each - * format/size combination for depth streams.</p> + * output format/size combination for depth streams.</p> * <p>A stall duration is how much extra time would get added * to the normal minimum frame duration for a repeating request * that has streams with non-zero stall.</p> diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 51b326b..f6791a4 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -54,6 +54,7 @@ public abstract class CameraDevice implements AutoCloseable { * means that high frame rate is given priority over the highest-quality * post-processing. These requests would normally be used with the * {@link CameraCaptureSession#setRepeatingRequest} method. + * This template is guaranteed to be supported on all camera devices. * * @see #createCaptureRequest */ @@ -63,6 +64,7 @@ public abstract class CameraDevice implements AutoCloseable { * Create a request suitable for still image capture. Specifically, this * means prioritizing image quality over frame rate. These requests would * commonly be used with the {@link CameraCaptureSession#capture} method. + * This template is guaranteed to be supported on all camera devices. * * @see #createCaptureRequest */ @@ -73,6 +75,7 @@ public abstract class CameraDevice implements AutoCloseable { * that a stable frame rate is used, and post-processing is set for * recording quality. These requests would commonly be used with the * {@link CameraCaptureSession#setRepeatingRequest} method. + * This template is guaranteed to be supported on all camera devices. * * @see #createCaptureRequest */ @@ -84,6 +87,9 @@ public abstract class CameraDevice implements AutoCloseable { * disrupting the ongoing recording. These requests would commonly be used * with the {@link CameraCaptureSession#capture} method while a request based on * {@link #TEMPLATE_RECORD} is is in use with {@link CameraCaptureSession#setRepeatingRequest}. + * This template is guaranteed to be supported on all camera devices except + * legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL} + * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) * * @see #createCaptureRequest */ @@ -93,6 +99,11 @@ public abstract class CameraDevice implements AutoCloseable { * Create a request suitable for zero shutter lag still capture. This means * means maximizing image quality without compromising preview frame rate. * AE/AWB/AF should be on auto mode. + * This template is guaranteed to be supported on camera devices that support the + * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING OPAQUE_REPROCESSING} + * capability or the + * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING} + * capability. * * @see #createCaptureRequest */ @@ -105,6 +116,9 @@ public abstract class CameraDevice implements AutoCloseable { * quality. The manual capture parameters (exposure, sensitivity, and so on) * are set to reasonable defaults, but should be overriden by the * application depending on the intended use case. + * This template is guaranteed to be supported on camera devices that support the + * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR MANUAL_SENSOR} + * capability. * * @see #createCaptureRequest */ @@ -473,12 +487,14 @@ public abstract class CameraDevice implements AutoCloseable { * settings as desired, instead.</p> * * @param templateType An enumeration selecting the use case for this - * request; one of the CameraDevice.TEMPLATE_ values. + * request; one of the CameraDevice.TEMPLATE_ values. Not all template + * types are supported on every device. See the documentation for each + * template type for details. * @return a builder for a capture request, initialized with default * settings for that template, and no output streams * - * @throws IllegalArgumentException if the templateType is not in the list - * of supported templates. + * @throws IllegalArgumentException if the templateType is not supported by + * this device. * @throws CameraAccessException if the camera device is no longer connected or has * encountered a fatal error * @throws IllegalStateException if the camera device has been closed diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index e3f1d73..ca9439b 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -461,22 +461,21 @@ public abstract class CameraMetadata<TKey> { * <p>The camera device supports the Zero Shutter Lag reprocessing use case.</p> * <ul> * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li> - * <li>ImageFormat#PRIVATE is supported as an output/input format, that is, - * ImageFormat#PRIVATE is included in the lists of formats returned by - * StreamConfigurationMap#getInputFormats and - * StreamConfigurationMap#getOutputFormats.</li> - * <li>StreamConfigurationMap#getValidOutputFormatsForInput returns non empty int[] for - * each supported input format returned by StreamConfigurationMap#getInputFormats.</li> - * <li>Each size returned by StreamConfigurationMap#getInputSizes(ImageFormat#PRIVATE) - * is also included in StreamConfigurationMap#getOutputSizes(ImageFormat#PRIVATE)</li> - * <li>Using ImageFormat#PRIVATE does not cause a frame rate drop - * relative to the sensor's maximum capture rate (at that - * resolution).</li> - * <li>ImageFormat#PRIVATE will be reprocessable into both YUV_420_888 - * and JPEG formats.</li> + * <li>{@link android.graphics.ImageFormat#PRIVATE } is supported as an output/input format, + * that is, {@link android.graphics.ImageFormat#PRIVATE } is included in the lists of + * formats returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats } and {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputFormats }.</li> + * <li>{@link android.hardware.camera2.params.StreamConfigurationMap#getValidOutputFormatsForInput } + * returns non empty int[] for each supported input format returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats }.</li> + * <li>Each size returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputSizes getInputSizes(ImageFormat.PRIVATE)} is also included in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes getOutputSizes(ImageFormat.PRIVATE)}</li> + * <li>Using {@link android.graphics.ImageFormat#PRIVATE } does not cause a frame rate drop + * relative to the sensor's maximum capture rate (at that resolution).</li> + * <li>{@link android.graphics.ImageFormat#PRIVATE } will be reprocessable into both + * {@link android.graphics.ImageFormat#YUV_420_888 } and + * {@link android.graphics.ImageFormat#JPEG } formats.</li> * <li>The maximum available resolution for OPAQUE streams * (both input/output) will match the maximum available * resolution of JPEG streams.</li> + * <li>Static metadata {@link CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL android.reprocess.maxCaptureStall}.</li> * <li>Only below controls are effective for reprocessing requests and * will be present in capture results, other controls in reprocess * requests will be ignored by the camera device.<ul> @@ -489,6 +488,7 @@ public abstract class CameraMetadata<TKey> { * * @see CaptureRequest#EDGE_MODE * @see CaptureRequest#NOISE_REDUCTION_MODE + * @see CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ @@ -569,25 +569,25 @@ public abstract class CameraMetadata<TKey> { * following:</p> * <ul> * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li> - * <li>YUV_420_888 is supported as an output/input format, that is, + * <li>{@link android.graphics.ImageFormat#YUV_420_888 } is supported as an output/input format, that is, * YUV_420_888 is included in the lists of formats returned by - * StreamConfigurationMap#getInputFormats and - * StreamConfigurationMap#getOutputFormats.</li> - * <li>StreamConfigurationMap#getValidOutputFormatsForInput returns non empty int[] for - * each supported input format returned by StreamConfigurationMap#getInputFormats.</li> - * <li>Each size returned by StreamConfigurationMap#getInputSizes(YUV_420_888) - * is also included in StreamConfigurationMap#getOutputSizes(YUV_420_888)</li> - * <li>Using YUV_420_888 does not cause a frame rate drop + * {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats } and + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputFormats }.</li> + * <li>{@link android.hardware.camera2.params.StreamConfigurationMap#getValidOutputFormatsForInput } + * returns non-empty int[] for each supported input format returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats }.</li> + * <li>Each size returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputSizes getInputSizes(YUV_420_888)} is also included in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes getOutputSizes(YUV_420_888)}</li> + * <li>Using {@link android.graphics.ImageFormat#YUV_420_888 } does not cause a frame rate drop * relative to the sensor's maximum capture rate (at that resolution).</li> - * <li>YUV_420_888 will be reprocessable into both YUV_420_888 - * and JPEG formats.</li> - * <li>The maximum available resolution for YUV_420_888 streams - * (both input/output) will match the maximum available - * resolution of JPEG streams.</li> - * <li>Only the below controls are effective for reprocessing requests and will be - * present in capture results. The reprocess requests are from the original capture - * results that are assocaited with the intermidate YUV_420_888 output buffers. - * All other controls in the reprocess requests will be ignored by the camera device.<ul> + * <li>{@link android.graphics.ImageFormat#YUV_420_888 } will be reprocessable into both + * {@link android.graphics.ImageFormat#YUV_420_888 } and {@link android.graphics.ImageFormat#JPEG } formats.</li> + * <li>The maximum available resolution for {@link android.graphics.ImageFormat#YUV_420_888 } streams (both input/output) will match the + * maximum available resolution of {@link android.graphics.ImageFormat#JPEG } streams.</li> + * <li>Static metadata {@link CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL android.reprocess.maxCaptureStall}.</li> + * <li>Only the below controls are effective for reprocessing requests and will be present + * in capture results. The reprocess requests are from the original capture results that + * are associated with the intermediate {@link android.graphics.ImageFormat#YUV_420_888 } + * output buffers. All other controls in the reprocess requests will be ignored by the + * camera device.<ul> * <li>android.jpeg.*</li> * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li> * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li> @@ -599,6 +599,7 @@ public abstract class CameraMetadata<TKey> { * @see CaptureRequest#EDGE_MODE * @see CaptureRequest#NOISE_REDUCTION_MODE * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR + * @see CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ @@ -608,11 +609,13 @@ public abstract class CameraMetadata<TKey> { * <p>The camera device can produce depth measurements from its field of view.</p> * <p>This capability requires the camera device to support the following:</p> * <ul> - * <li>DEPTH16 is supported as an output format.</li> - * <li>DEPTH_POINT_CLOUD is optionally supported as an output format.</li> - * <li>This camera device, and all camera devices with the same android.lens.info.facing, - * will list the following calibration entries in both CameraCharacteristics and - * CaptureResults:<ul> + * <li>{@link android.graphics.ImageFormat#DEPTH16 } is supported as an output format.</li> + * <li>{@link android.graphics.ImageFormat#DEPTH_POINT_CLOUD } is optionally supported as an + * output format.</li> + * <li>This camera device, and all camera devices with the same {@link CameraCharacteristics#LENS_FACING android.lens.facing}, + * will list the following calibration entries in both + * {@link android.hardware.camera2.CameraCharacteristics } and + * {@link android.hardware.camera2.CaptureResult }:<ul> * <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li> * <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li> * <li>android.lens.intrinsicCalibration</li> @@ -627,13 +630,14 @@ public abstract class CameraMetadata<TKey> { * <p>Generally, depth output operates at a slower frame rate than standard color capture, * so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that * should be accounted for (see - * android.hardware.camera2.StreamConfigurationMap#getOutputStallDuration). On a device - * that supports both depth and color-based output, to enable smooth preview, using a - * repeating burst is recommended, where a depth-output target is only included once - * every N frames, where N is the ratio between preview output rate and depth output + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }). + * On a device that supports both depth and color-based output, to enable smooth preview, + * using a repeating burst is recommended, where a depth-output target is only included + * once every N frames, where N is the ratio between preview output rate and depth output * rate, including depth stall time.</p> * * @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE + * @see CameraCharacteristics#LENS_FACING * @see CameraCharacteristics#LENS_POSE_ROTATION * @see CameraCharacteristics#LENS_POSE_TRANSLATION * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES @@ -707,7 +711,7 @@ public abstract class CameraMetadata<TKey> { /** * <p>Timestamps from {@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp} are in the same timebase as - * android.os.SystemClock#elapsedRealtimeNanos(), + * {@link android.os.SystemClock#elapsedRealtimeNanos }, * and they can be compared to other timestamps using that base.</p> * * @see CaptureResult#SENSOR_TIMESTAMP @@ -866,7 +870,7 @@ public abstract class CameraMetadata<TKey> { /** * <p>Every frame has the requests immediately applied.</p> * <p>Furthermore for all results, - * <code>android.sync.frameNumber == CaptureResult#getFrameNumber()</code></p> + * <code>android.sync.frameNumber == {@link android.hardware.camera2.CaptureResult#getFrameNumber }</code></p> * <p>Changing controls over multiple requests one after another will * produce results that have those controls applied atomically * each frame.</p> diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 19d17b1..ab6ce91 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -1275,8 +1275,9 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>This control (except for MANUAL) is only effective if * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p> * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} - * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} - * contains MANUAL_SENSOR. Other intent values are always supported.</p> + * contains OPAQUE_REPROCESSING or YUV_REPROCESSING. MANUAL will be supported if + * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR. Other intent values are + * always supported.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li> @@ -2039,8 +2040,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * cannot process more than 1 capture at a time.</li> * </ul> * <p>The necessary information for the application, given the model above, - * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field - * using StreamConfigurationMap#getOutputMinFrameDuration(int, Size). + * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field using + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }. * These are used to determine the maximum frame rate / minimum frame * duration that is possible for a given stream configuration.</p> * <p>Specifically, the application can use the following rules to @@ -2049,21 +2050,19 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <ol> * <li>Let the set of currently configured input/output streams * be called <code>S</code>.</li> - * <li>Find the minimum frame durations for each stream in <code>S</code>, by - * looking it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using - * StreamConfigurationMap#getOutputMinFrameDuration(int, Size) (with - * its respective size/format). Let this set of frame durations be called - * <code>F</code>.</li> + * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking + * it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration } + * (with its respective size/format). Let this set of frame durations be + * called <code>F</code>.</li> * <li>For any given request <code>R</code>, the minimum frame duration allowed * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams * used in <code>R</code> be called <code>S_r</code>.</li> * </ol> - * <p>If none of the streams in <code>S_r</code> have a stall time (listed in - * StreamConfigurationMap#getOutputStallDuration(int,Size) using its - * respective size/format), then the frame duration in - * <code>F</code> determines the steady state frame rate that the application will - * get if it uses <code>R</code> as a repeating request. Let this special kind - * of request be called <code>Rsimple</code>.</p> + * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } + * using its respective size/format), then the frame duration in <code>F</code> + * determines the steady state frame rate that the application will get + * if it uses <code>R</code> as a repeating request. Let this special kind of + * request be called <code>Rsimple</code>.</p> * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved * by a single capture of a new request <code>Rstall</code> (which has at least * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the @@ -2071,7 +2070,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * if all buffers from the previous <code>Rstall</code> have already been * delivered.</p> * <p>For more details about stalling, see - * StreamConfigurationMap#getOutputStallDuration(int,Size).</p> + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p> * <p>This control is only effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} is set to * OFF; otherwise the auto-exposure algorithm will override this value.</p> * <p><b>Units</b>: Nanoseconds</p> @@ -2647,8 +2646,12 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p><b>Range of valid values:</b><br> * >= 1.0</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> * * @see CaptureRequest#EDGE_MODE + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL * @see CaptureRequest#NOISE_REDUCTION_MODE * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index ef5d75c..3dc8970 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -1698,8 +1698,9 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>This control (except for MANUAL) is only effective if * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p> * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} - * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} - * contains MANUAL_SENSOR. Other intent values are always supported.</p> + * contains OPAQUE_REPROCESSING or YUV_REPROCESSING. MANUAL will be supported if + * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR. Other intent values are + * always supported.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li> @@ -2885,8 +2886,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * cannot process more than 1 capture at a time.</li> * </ul> * <p>The necessary information for the application, given the model above, - * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field - * using StreamConfigurationMap#getOutputMinFrameDuration(int, Size). + * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field using + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }. * These are used to determine the maximum frame rate / minimum frame * duration that is possible for a given stream configuration.</p> * <p>Specifically, the application can use the following rules to @@ -2895,21 +2896,19 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <ol> * <li>Let the set of currently configured input/output streams * be called <code>S</code>.</li> - * <li>Find the minimum frame durations for each stream in <code>S</code>, by - * looking it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using - * StreamConfigurationMap#getOutputMinFrameDuration(int, Size) (with - * its respective size/format). Let this set of frame durations be called - * <code>F</code>.</li> + * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking + * it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration } + * (with its respective size/format). Let this set of frame durations be + * called <code>F</code>.</li> * <li>For any given request <code>R</code>, the minimum frame duration allowed * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams * used in <code>R</code> be called <code>S_r</code>.</li> * </ol> - * <p>If none of the streams in <code>S_r</code> have a stall time (listed in - * StreamConfigurationMap#getOutputStallDuration(int,Size) using its - * respective size/format), then the frame duration in - * <code>F</code> determines the steady state frame rate that the application will - * get if it uses <code>R</code> as a repeating request. Let this special kind - * of request be called <code>Rsimple</code>.</p> + * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } + * using its respective size/format), then the frame duration in <code>F</code> + * determines the steady state frame rate that the application will get + * if it uses <code>R</code> as a repeating request. Let this special kind of + * request be called <code>Rsimple</code>.</p> * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved * by a single capture of a new request <code>Rstall</code> (which has at least * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the @@ -2917,7 +2916,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * if all buffers from the previous <code>Rstall</code> have already been * delivered.</p> * <p>For more details about stalling, see - * StreamConfigurationMap#getOutputStallDuration(int,Size).</p> + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p> * <p>This control is only effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} is set to * OFF; otherwise the auto-exposure algorithm will override this value.</p> * <p><b>Units</b>: Nanoseconds</p> @@ -2979,11 +2978,10 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * and are monotonically increasing. They can be compared with the * timestamps for other captures from the same camera device, but are * not guaranteed to be comparable to any other time source.</p> - * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} <code>==</code> REALTIME, - * the timestamps measure time in the same timebase as - * android.os.SystemClock#elapsedRealtimeNanos(), and they can be - * compared to other timestamps from other subsystems that are using - * that base.</p> + * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} <code>==</code> REALTIME, the + * timestamps measure time in the same timebase as {@link android.os.SystemClock#elapsedRealtimeNanos }, and they can + * be compared to other timestamps from other subsystems that + * are using that base.</p> * <p><b>Units</b>: Nanoseconds</p> * <p><b>Range of valid values:</b><br> * > 0</p> @@ -3141,7 +3139,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p><b>Units</b>: Nanoseconds</p> * <p><b>Range of valid values:</b><br> * >= 0 and < - * StreamConfigurationMap#getOutputMinFrameDuration(int, Size).</p> + * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * <p><b>Limited capability</b> - * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the @@ -3966,8 +3964,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p><b>Range of valid values:</b><br> * >= 1.0</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> + * <p><b>Limited capability</b> - + * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> * * @see CaptureRequest#EDGE_MODE + * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL * @see CaptureRequest#NOISE_REDUCTION_MODE * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index adab9be..02793f1 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -182,6 +182,10 @@ public abstract class DisplayManagerInternal { // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter). public float screenAutoBrightnessAdjustment; + // Set to true if screenBrightness and screenAutoBrightnessAdjustment were both + // set by the user as opposed to being programmatically controlled by apps. + public boolean brightnessSetByUser; + // If true, enables automatic brightness control. public boolean useAutoBrightness; @@ -229,6 +233,7 @@ public abstract class DisplayManagerInternal { useProximitySensor = other.useProximitySensor; screenBrightness = other.screenBrightness; screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment; + brightnessSetByUser = other.brightnessSetByUser; useAutoBrightness = other.useAutoBrightness; blockScreenOn = other.blockScreenOn; lowPowerMode = other.lowPowerMode; @@ -249,6 +254,7 @@ public abstract class DisplayManagerInternal { && useProximitySensor == other.useProximitySensor && screenBrightness == other.screenBrightness && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment + && brightnessSetByUser == other.brightnessSetByUser && useAutoBrightness == other.useAutoBrightness && blockScreenOn == other.blockScreenOn && lowPowerMode == other.lowPowerMode @@ -268,6 +274,7 @@ public abstract class DisplayManagerInternal { + ", useProximitySensor=" + useProximitySensor + ", screenBrightness=" + screenBrightness + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment + + ", brightnessSetByUser=" + brightnessSetByUser + ", useAutoBrightness=" + useAutoBrightness + ", blockScreenOn=" + blockScreenOn + ", lowPowerMode=" + lowPowerMode diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java index 1a42319..410d550 100644 --- a/core/java/android/hardware/usb/UsbDevice.java +++ b/core/java/android/hardware/usb/UsbDevice.java @@ -45,6 +45,7 @@ public class UsbDevice implements Parcelable { private final String mName; private final String mManufacturerName; private final String mProductName; + private final String mVersion; private final String mSerialNumber; private final int mVendorId; private final int mProductId; @@ -62,7 +63,7 @@ public class UsbDevice implements Parcelable { */ public UsbDevice(String name, int vendorId, int productId, int Class, int subClass, int protocol, - String manufacturerName, String productName, String serialNumber) { + String manufacturerName, String productName, String version, String serialNumber) { mName = name; mVendorId = vendorId; mProductId = productId; @@ -71,6 +72,7 @@ public class UsbDevice implements Parcelable { mProtocol = protocol; mManufacturerName = manufacturerName; mProductName = productName; + mVersion = version; mSerialNumber = serialNumber; } @@ -104,6 +106,15 @@ public class UsbDevice implements Parcelable { } /** + * Returns the version number of the device. + * + * @return the device version + */ + public String getVersion() { + return mVersion; + } + + /** * Returns the serial number of the device. * * @return the serial number name @@ -263,7 +274,7 @@ public class UsbDevice implements Parcelable { ",mVendorId=" + mVendorId + ",mProductId=" + mProductId + ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol + ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName + - ",mSerialNumber=" + mSerialNumber + ",mConfigurations=["); + ",mVersion=" + mVersion + ",mSerialNumber=" + mSerialNumber + ",mConfigurations=["); for (int i = 0; i < mConfigurations.length; i++) { builder.append("\n"); builder.append(mConfigurations[i].toString()); @@ -283,10 +294,11 @@ public class UsbDevice implements Parcelable { int protocol = in.readInt(); String manufacturerName = in.readString(); String productName = in.readString(); + String version = in.readString(); String serialNumber = in.readString(); Parcelable[] configurations = in.readParcelableArray(UsbInterface.class.getClassLoader()); UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, - manufacturerName, productName, serialNumber); + manufacturerName, productName, version, serialNumber); device.setConfigurations(configurations); return device; } @@ -309,6 +321,7 @@ public class UsbDevice implements Parcelable { parcel.writeInt(mProtocol); parcel.writeString(mManufacturerName); parcel.writeString(mProductName); + parcel.writeString(mVersion); parcel.writeString(mSerialNumber); parcel.writeParcelableArray(mConfigurations, 0); } diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index c722fbc..7f5f377 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -38,8 +38,6 @@ interface INetworkPolicyManager { boolean isUidForeground(int uid); - int[] getPowerSaveAppIdWhitelist(); - void registerListener(INetworkPolicyListener listener); void unregisterListener(INetworkPolicyListener listener); diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index bc03637..ecc3fb4 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -41,6 +41,7 @@ import java.util.HashSet; */ public class NetworkPolicyManager { + /* POLICY_* are masks and can be ORed */ /** No specific network policy, use system default. */ public static final int POLICY_NONE = 0x0; /** Reject network usage on metered networks when application in background. */ @@ -48,10 +49,17 @@ public class NetworkPolicyManager { /** Allow network use (metered or not) in the background in battery save mode. */ public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2; + /* RULE_* are not masks and they must be exclusive */ /** All network traffic should be allowed. */ public static final int RULE_ALLOW_ALL = 0x0; /** Reject traffic on metered networks. */ public static final int RULE_REJECT_METERED = 0x1; + /** Reject traffic on all networks. */ + public static final int RULE_REJECT_ALL = 0x2; + + public static final int FIREWALL_RULE_DEFAULT = 0; + public static final int FIREWALL_RULE_ALLOW = 1; + public static final int FIREWALL_RULE_DENY = 2; private static final boolean ALLOW_PLATFORM_APP_POLICY = true; @@ -80,7 +88,7 @@ public class NetworkPolicyManager { * Set policy flags for specific UID. * * @param policy {@link #POLICY_NONE} or combination of flags like - * {@link #POLICY_REJECT_METERED_BACKGROUND}, {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. + * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. */ public void setUidPolicy(int uid, int policy) { try { @@ -129,14 +137,6 @@ public class NetworkPolicyManager { } } - public int[] getPowerSaveAppIdWhitelist() { - try { - return mService.getPowerSaveAppIdWhitelist(); - } catch (RemoteException e) { - return new int[0]; - } - } - public void registerListener(INetworkPolicyListener listener) { try { mService.registerListener(listener); @@ -330,6 +330,8 @@ public class NetworkPolicyManager { fout.write("["); if ((rules & RULE_REJECT_METERED) != 0) { fout.write("REJECT_METERED"); + } else if ((rules & RULE_REJECT_ALL) != 0) { + fout.write("REJECT_ALL"); } fout.write("]"); } diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl new file mode 100644 index 0000000..3cb29ff --- /dev/null +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** @hide */ +interface IDeviceIdleController { + void addPowerSaveWhitelistApp(String name); + void removePowerSaveWhitelistApp(String name); + String[] getSystemPowerWhitelist(); + String[] getFullPowerWhitelist(); + int[] getAppIdWhitelist(); +} diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index f93550a..b29e8d0 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -342,7 +342,7 @@ interface INetworkManagementService void setFirewallInterfaceRule(String iface, boolean allow); void setFirewallEgressSourceRule(String addr, boolean allow); void setFirewallEgressDestRule(String addr, int port, boolean allow); - void setFirewallUidRule(int uid, boolean allow); + void setFirewallUidRule(int uid, int rule); /** * Set all packets from users in ranges to go through VPN specified by netId. diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl index 73a68f1..0cc1603 100644 --- a/core/java/android/os/IPermissionController.aidl +++ b/core/java/android/os/IPermissionController.aidl @@ -20,4 +20,5 @@ package android.os; /** @hide */ interface IPermissionController { boolean checkPermission(String permission, int pid, int uid); + String[] getPackagesForUid(int uid); } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 01c9a21..1d9d7d2 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -920,6 +920,14 @@ public final class PowerManager { = "android.os.action.DEVICE_IDLE_MODE_CHANGED"; /** + * @hide Intent that is broadcast when the set of power save whitelist apps has changed. + * This broadcast is only sent to registered receivers. + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_POWER_SAVE_WHITELIST_CHANGED + = "android.os.action.POWER_SAVE_WHITELIST_CHANGED"; + + /** * Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change. * This broadcast is only sent to registered receivers. * diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 16e0bf7..fcde3f4 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -942,6 +942,24 @@ public interface IMountService extends IInterface { } @Override + public VolumeRecord[] getVolumeRecords(int _flags) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + VolumeRecord[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(_flags); + mRemote.transact(Stub.TRANSACTION_getVolumeRecords, _data, _reply, 0); + _reply.readException(); + _result = _reply.createTypedArray(VolumeRecord.CREATOR); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override public void mount(String volId) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); @@ -1033,12 +1051,12 @@ public interface IMountService extends IInterface { } @Override - public void setVolumeNickname(String volId, String nickname) throws RemoteException { + public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(volId); + _data.writeString(fsUuid); _data.writeString(nickname); mRemote.transact(Stub.TRANSACTION_setVolumeNickname, _data, _reply, 0); _reply.readException(); @@ -1049,12 +1067,12 @@ public interface IMountService extends IInterface { } @Override - public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException { + public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(volId); + _data.writeString(fsUuid); _data.writeInt(flags); _data.writeInt(mask); mRemote.transact(Stub.TRANSACTION_setVolumeUserFlags, _data, _reply, 0); @@ -1066,6 +1084,21 @@ public interface IMountService extends IInterface { } @Override + public void forgetVolume(String fsUuid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(fsUuid); + mRemote.transact(Stub.TRANSACTION_forgetVolume, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } + + @Override public String getPrimaryStorageUuid() throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); @@ -1192,20 +1225,22 @@ public interface IMountService extends IInterface { static final int TRANSACTION_getDisks = IBinder.FIRST_CALL_TRANSACTION + 44; static final int TRANSACTION_getVolumes = IBinder.FIRST_CALL_TRANSACTION + 45; + static final int TRANSACTION_getVolumeRecords = IBinder.FIRST_CALL_TRANSACTION + 46; - static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 46; - static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 47; - static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 48; + static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 47; + static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 48; + static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 49; - static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 49; - static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 50; - static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 51; + static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 50; + static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 51; + static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 52; - static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 52; - static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 53; + static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 53; + static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 54; + static final int TRANSACTION_forgetVolume = IBinder.FIRST_CALL_TRANSACTION + 55; - static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 54; - static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 55; + static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 56; + static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 57; /** * Cast an IBinder object into an IMountService interface, generating a @@ -1647,6 +1682,14 @@ public interface IMountService extends IInterface { reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); return true; } + case TRANSACTION_getVolumeRecords: { + data.enforceInterface(DESCRIPTOR); + int _flags = data.readInt(); + VolumeRecord[] volumes = getVolumeRecords(_flags); + reply.writeNoException(); + reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + return true; + } case TRANSACTION_mount: { data.enforceInterface(DESCRIPTOR); String volId = data.readString(); @@ -1707,6 +1750,13 @@ public interface IMountService extends IInterface { reply.writeNoException(); return true; } + case TRANSACTION_forgetVolume: { + data.enforceInterface(DESCRIPTOR); + String fsUuid = data.readString(); + forgetVolume(fsUuid); + reply.writeNoException(); + return true; + } case TRANSACTION_getPrimaryStorageUuid: { data.enforceInterface(DESCRIPTOR); String volumeUuid = getPrimaryStorageUuid(); @@ -2012,6 +2062,7 @@ public interface IMountService extends IInterface { public DiskInfo[] getDisks() throws RemoteException; public VolumeInfo[] getVolumes(int flags) throws RemoteException; + public VolumeRecord[] getVolumeRecords(int flags) throws RemoteException; public void mount(String volId) throws RemoteException; public void unmount(String volId) throws RemoteException; @@ -2021,8 +2072,9 @@ public interface IMountService extends IInterface { public void partitionPrivate(String diskId) throws RemoteException; public void partitionMixed(String diskId, int ratio) throws RemoteException; - public void setVolumeNickname(String volId, String nickname) throws RemoteException; - public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException; + public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException; + public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException; + public void forgetVolume(String fsUuid) throws RemoteException; public String getPrimaryStorageUuid() throws RemoteException; public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java index fcb4779..2d13e49 100644 --- a/core/java/android/os/storage/IMountServiceListener.java +++ b/core/java/android/os/storage/IMountServiceListener.java @@ -93,8 +93,8 @@ public interface IMountServiceListener extends IInterface { } case TRANSACTION_onVolumeMetadataChanged: { data.enforceInterface(DESCRIPTOR); - final VolumeInfo vol = (VolumeInfo) data.readParcelable(null); - onVolumeMetadataChanged(vol); + final String fsUuid = data.readString(); + onVolumeMetadataChanged(fsUuid); reply.writeNoException(); return true; } @@ -192,12 +192,12 @@ public interface IMountServiceListener extends IInterface { } @Override - public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException { + public void onVolumeMetadataChanged(String fsUuid) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeParcelable(vol, 0); + _data.writeString(fsUuid); mRemote.transact(Stub.TRANSACTION_onVolumeMetadataChanged, _data, _reply, android.os.IBinder.FLAG_ONEWAY); _reply.readException(); @@ -253,7 +253,7 @@ public interface IMountServiceListener extends IInterface { public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) throws RemoteException; - public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException; + public void onVolumeMetadataChanged(String fsUuid) throws RemoteException; public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException; } diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java index 6a0140e..536aca9 100644 --- a/core/java/android/os/storage/StorageEventListener.java +++ b/core/java/android/os/storage/StorageEventListener.java @@ -41,7 +41,7 @@ public class StorageEventListener { public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { } - public void onVolumeMetadataChanged(VolumeInfo vol) { + public void onVolumeMetadataChanged(String fsUuid) { } public void onDiskScanned(DiskInfo disk, int volumeCount) { diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 6116aef..29da4f1 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -34,6 +34,7 @@ import android.os.ServiceManager; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; +import android.util.Slog; import android.util.SparseArray; import com.android.internal.os.SomeArgs; @@ -79,9 +80,6 @@ public class StorageManager { /** {@hide} */ public static final String UUID_PRIMARY_PHYSICAL = "primary_physical"; - /** {@hide} */ - public static final int FLAG_ALL_METADATA = 1 << 0; - private final Context mContext; private final ContentResolver mResolver; @@ -120,7 +118,7 @@ public class StorageManager { args.recycle(); return true; case MSG_VOLUME_METADATA_CHANGED: - mCallback.onVolumeMetadataChanged((VolumeInfo) args.arg1); + mCallback.onVolumeMetadataChanged((String) args.arg1); args.recycle(); return true; case MSG_DISK_SCANNED: @@ -156,9 +154,9 @@ public class StorageManager { } @Override - public void onVolumeMetadataChanged(VolumeInfo vol) { + public void onVolumeMetadataChanged(String fsUuid) { final SomeArgs args = SomeArgs.obtain(); - args.arg1 = vol; + args.arg1 = fsUuid; mHandler.obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget(); } @@ -516,6 +514,18 @@ public class StorageManager { } /** {@hide} */ + public @Nullable VolumeRecord findRecordByUuid(String fsUuid) { + Preconditions.checkNotNull(fsUuid); + // TODO; go directly to service to make this faster + for (VolumeRecord rec : getVolumeRecords()) { + if (Objects.equals(rec.fsUuid, fsUuid)) { + return rec; + } + } + return null; + } + + /** {@hide} */ public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) { return findVolumeById(emulatedVol.getId().replace("emulated", "private")); } @@ -527,13 +537,17 @@ public class StorageManager { /** {@hide} */ public @NonNull List<VolumeInfo> getVolumes() { - return getVolumes(0); + try { + return Arrays.asList(mMountService.getVolumes(0)); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } } /** {@hide} */ - public @NonNull List<VolumeInfo> getVolumes(int flags) { + public @NonNull List<VolumeRecord> getVolumeRecords() { try { - return Arrays.asList(mMountService.getVolumes(flags)); + return Arrays.asList(mMountService.getVolumeRecords(0)); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -541,13 +555,23 @@ public class StorageManager { /** {@hide} */ public @Nullable String getBestVolumeDescription(VolumeInfo vol) { - String descrip = vol.getDescription(); - if (vol.disk != null) { - if (TextUtils.isEmpty(descrip)) { - descrip = vol.disk.getDescription(); + // Nickname always takes precedence when defined + if (!TextUtils.isEmpty(vol.fsUuid)) { + final VolumeRecord rec = findRecordByUuid(vol.fsUuid); + if (!TextUtils.isEmpty(rec.nickname)) { + return rec.nickname; } } - return descrip; + + if (!TextUtils.isEmpty(vol.getDescription())) { + return vol.getDescription(); + } + + if (vol.disk != null) { + return vol.disk.getDescription(); + } + + return null; } /** {@hide} */ @@ -616,29 +640,62 @@ public class StorageManager { } /** {@hide} */ - public void setVolumeNickname(String volId, String nickname) { + public void wipeAdoptableDisks() { + // We only wipe devices in "adoptable" locations, which are in a + // long-term stable slot/location on the device, where apps have a + // reasonable chance of storing sensitive data. (Apps need to go through + // SAF to write to transient volumes.) + final List<DiskInfo> disks = getDisks(); + for (DiskInfo disk : disks) { + final String diskId = disk.getId(); + if (disk.isAdoptable()) { + Slog.d(TAG, "Found adoptable " + diskId + "; wiping"); + try { + // TODO: switch to explicit wipe command when we have it, + // for now rely on the fact that vfat format does a wipe + mMountService.partitionPublic(diskId); + } catch (Exception e) { + Slog.w(TAG, "Failed to wipe " + diskId + ", but soldiering onward", e); + } + } else { + Slog.d(TAG, "Ignorning non-adoptable disk " + disk.getId()); + } + } + } + + /** {@hide} */ + public void setVolumeNickname(String fsUuid, String nickname) { + try { + mMountService.setVolumeNickname(fsUuid, nickname); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** {@hide} */ + public void setVolumeInited(String fsUuid, boolean inited) { try { - mMountService.setVolumeNickname(volId, nickname); + mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0, + VolumeRecord.USER_FLAG_INITED); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** {@hide} */ - public void setVolumeInited(String volId, boolean inited) { + public void setVolumeSnoozed(String fsUuid, boolean snoozed) { try { - mMountService.setVolumeUserFlags(volId, inited ? VolumeInfo.USER_FLAG_INITED : 0, - VolumeInfo.USER_FLAG_INITED); + mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0, + VolumeRecord.USER_FLAG_SNOOZED); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** {@hide} */ - public void setVolumeSnoozed(String volId, boolean snoozed) { + public void forgetVolume(String fsUuid) { try { - mMountService.setVolumeUserFlags(volId, snoozed ? VolumeInfo.USER_FLAG_SNOOZED : 0, - VolumeInfo.USER_FLAG_SNOOZED); + mMountService.forgetVolume(fsUuid); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index 4e9cfc7..fd10cae 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -78,9 +78,6 @@ public class VolumeInfo implements Parcelable { public static final int MOUNT_FLAG_PRIMARY = 1 << 0; public static final int MOUNT_FLAG_VISIBLE = 1 << 1; - public static final int USER_FLAG_INITED = 1 << 0; - public static final int USER_FLAG_SNOOZED = 1 << 1; - private static SparseArray<String> sStateToEnvironment = new SparseArray<>(); private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); @@ -135,8 +132,6 @@ public class VolumeInfo implements Parcelable { /** Framework state */ public final int mtpIndex; - public String nickname; - public int userFlags = 0; public VolumeInfo(String id, int type, DiskInfo disk, int mtpIndex) { this.id = Preconditions.checkNotNull(id); @@ -161,8 +156,6 @@ public class VolumeInfo implements Parcelable { fsLabel = parcel.readString(); path = parcel.readString(); mtpIndex = parcel.readInt(); - nickname = parcel.readString(); - userFlags = parcel.readInt(); } public static @NonNull String getEnvironmentForState(int state) { @@ -210,10 +203,6 @@ public class VolumeInfo implements Parcelable { return fsUuid; } - public @Nullable String getNickname() { - return nickname; - } - public int getMountUserId() { return mountUserId; } @@ -221,8 +210,6 @@ public class VolumeInfo implements Parcelable { public @Nullable String getDescription() { if (ID_PRIVATE_INTERNAL.equals(id)) { return Resources.getSystem().getString(com.android.internal.R.string.storage_internal); - } else if (!TextUtils.isEmpty(nickname)) { - return nickname; } else if (!TextUtils.isEmpty(fsLabel)) { return fsLabel; } else { @@ -250,14 +237,6 @@ public class VolumeInfo implements Parcelable { return (mountFlags & MOUNT_FLAG_VISIBLE) != 0; } - public boolean isInited() { - return (userFlags & USER_FLAG_INITED) != 0; - } - - public boolean isSnoozed() { - return (userFlags & USER_FLAG_SNOOZED) != 0; - } - public boolean isVisibleToUser(int userId) { if (type == TYPE_PUBLIC && userId == this.mountUserId) { return isVisible(); @@ -394,8 +373,6 @@ public class VolumeInfo implements Parcelable { pw.println(); pw.printPair("path", path); pw.printPair("mtpIndex", mtpIndex); - pw.printPair("nickname", nickname); - pw.printPair("userFlags", DebugUtils.flagsToString(getClass(), "USER_FLAG_", userFlags)); pw.decreaseIndent(); pw.println(); } @@ -461,7 +438,5 @@ public class VolumeInfo implements Parcelable { parcel.writeString(fsLabel); parcel.writeString(path); parcel.writeInt(mtpIndex); - parcel.writeString(nickname); - parcel.writeInt(userFlags); } } diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java new file mode 100644 index 0000000..096e2dd --- /dev/null +++ b/core/java/android/os/storage/VolumeRecord.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os.storage; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DebugUtils; + +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * Metadata for a storage volume which may not be currently present. + * + * @hide + */ +public class VolumeRecord implements Parcelable { + public static final String EXTRA_FS_UUID = + "android.os.storage.extra.FS_UUID"; + + public static final int USER_FLAG_INITED = 1 << 0; + public static final int USER_FLAG_SNOOZED = 1 << 1; + + public final int type; + public final String fsUuid; + public String nickname; + public int userFlags; + + public VolumeRecord(int type, String fsUuid) { + this.type = type; + this.fsUuid = Preconditions.checkNotNull(fsUuid); + } + + public VolumeRecord(Parcel parcel) { + type = parcel.readInt(); + fsUuid = parcel.readString(); + nickname = parcel.readString(); + userFlags = parcel.readInt(); + } + + public int getType() { + return type; + } + + public String getFsUuid() { + return fsUuid; + } + + public String getNickname() { + return nickname; + } + + public boolean isInited() { + return (userFlags & USER_FLAG_INITED) != 0; + } + + public boolean isSnoozed() { + return (userFlags & USER_FLAG_SNOOZED) != 0; + } + + public void dump(IndentingPrintWriter pw) { + pw.println("VolumeRecord:"); + pw.increaseIndent(); + pw.printPair("type", DebugUtils.valueToString(VolumeInfo.class, "TYPE_", type)); + pw.printPair("fsUuid", fsUuid); + pw.printPair("nickname", nickname); + pw.printPair("userFlags", + DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags)); + pw.decreaseIndent(); + pw.println(); + } + + @Override + public VolumeRecord clone() { + final Parcel temp = Parcel.obtain(); + try { + writeToParcel(temp, 0); + temp.setDataPosition(0); + return CREATOR.createFromParcel(temp); + } finally { + temp.recycle(); + } + } + + @Override + public boolean equals(Object o) { + if (o instanceof VolumeRecord) { + return Objects.equals(fsUuid, ((VolumeRecord) o).fsUuid); + } else { + return false; + } + } + + @Override + public int hashCode() { + return fsUuid.hashCode(); + } + + public static final Creator<VolumeRecord> CREATOR = new Creator<VolumeRecord>() { + @Override + public VolumeRecord createFromParcel(Parcel in) { + return new VolumeRecord(in); + } + + @Override + public VolumeRecord[] newArray(int size) { + return new VolumeRecord[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(type); + parcel.writeString(fsUuid); + parcel.writeString(nickname); + parcel.writeInt(userFlags); + } +} diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java index b3a3aad..458f153 100644 --- a/core/java/android/security/keymaster/KeyCharacteristics.java +++ b/core/java/android/security/keymaster/KeyCharacteristics.java @@ -105,11 +105,11 @@ public class KeyCharacteristics implements Parcelable { } } - public boolean getBoolean(KeyCharacteristics keyCharacteristics, int tag) { - if (keyCharacteristics.hwEnforced.containsTag(tag)) { - return keyCharacteristics.hwEnforced.getBoolean(tag, false); + public boolean getBoolean(int tag) { + if (hwEnforced.containsTag(tag)) { + return hwEnforced.getBoolean(tag, false); } else { - return keyCharacteristics.swEnforced.getBoolean(tag, false); + return swEnforced.getBoolean(tag, false); } } } diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 14e947c..dc8f3ea 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -62,7 +62,7 @@ public class ZenModeConfig implements Parcelable { Calendar.WEDNESDAY, Calendar.THURSDAY }; public static final int[] WEEKEND_DAYS = { Calendar.FRIDAY, Calendar.SATURDAY }; - public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 }; + public static final int[] MINUTE_BUCKETS = generateMinuteBuckets(); private static final int SECONDS_MS = 1000; private static final int MINUTES_MS = 60 * SECONDS_MS; private static final int ZERO_VALUE_MS = 10 * SECONDS_MS; @@ -201,6 +201,18 @@ public class ZenModeConfig implements Parcelable { } } + private static int[] generateMinuteBuckets() { + final int maxHrs = 12; + final int[] buckets = new int[maxHrs + 3]; + buckets[0] = 15; + buckets[1] = 30; + buckets[2] = 45; + for (int i = 1; i <= maxHrs; i++) { + buckets[2 + i] = 60 * i; + } + return buckets; + } + public static String sourceToString(int source) { switch (source) { case SOURCE_ANYONE: @@ -298,10 +310,10 @@ public class ZenModeConfig implements Parcelable { throw new IndexOutOfBoundsException("bad source in config:" + rt.allowFrom); } } else if (MANUAL_TAG.equals(tag)) { - rt.manualRule = readRuleXml(parser); + rt.manualRule = readRuleXml(parser, false /*conditionRequired*/); } else if (AUTOMATIC_TAG.equals(tag)) { final String id = parser.getAttributeValue(null, RULE_ATT_ID); - final ZenRule automaticRule = readRuleXml(parser); + final ZenRule automaticRule = readRuleXml(parser, true /*conditionRequired*/); if (id != null && automaticRule != null) { rt.automaticRules.put(id, automaticRule); } @@ -341,7 +353,7 @@ public class ZenModeConfig implements Parcelable { out.endTag(null, ZEN_TAG); } - public static ZenRule readRuleXml(XmlPullParser parser) { + public static ZenRule readRuleXml(XmlPullParser parser, boolean conditionRequired) { final ZenRule rt = new ZenRule(); rt.enabled = safeBoolean(parser, RULE_ATT_ENABLED, true); rt.snoozing = safeBoolean(parser, RULE_ATT_SNOOZING, false); @@ -355,7 +367,7 @@ public class ZenModeConfig implements Parcelable { rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID); rt.component = safeComponentName(parser, RULE_ATT_COMPONENT); rt.condition = readConditionXml(parser); - return rt.condition != null ? rt : null; + return rt.condition != null || !conditionRequired ? rt : null; } public static void writeRuleXml(ZenRule rule, XmlSerializer out) throws IOException { diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java index e991d84..ce94315 100644 --- a/core/java/android/speech/RecognizerIntent.java +++ b/core/java/android/speech/RecognizerIntent.java @@ -403,4 +403,12 @@ public class RecognizerIntent { */ public static final String EXTRA_SUPPORTED_LANGUAGES = "android.speech.extra.SUPPORTED_LANGUAGES"; + + /** + * Optional boolean, to be used with {@link #ACTION_RECOGNIZE_SPEECH}, + * {@link #ACTION_VOICE_SEARCH_HANDS_FREE}, {@link #ACTION_WEB_SEARCH} to indicate whether to + * only use an offline speech recognition engine. The default is false, meaning that either + * network or offline recognition engines may be used. + */ + public static final String EXTRA_PREFER_OFFLINE = "android.speech.extra.PREFER_OFFLINE"; } diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java index a7d9503..ca37d49 100644 --- a/core/java/android/transition/TransitionInflater.java +++ b/core/java/android/transition/TransitionInflater.java @@ -214,7 +214,7 @@ public class TransitionInflater { sConstructors.put(className, constructor); } } - + constructor.setAccessible(true); return constructor.newInstance(mContext, attrs); } } catch (InstantiationException e) { diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index aefced8..558b8f5 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -74,6 +74,7 @@ public class EventLog { private static final byte LONG_TYPE = 1; private static final byte STRING_TYPE = 2; private static final byte LIST_TYPE = 3; + private static final byte FLOAT_TYPE = 4; /** @param data containing event, read from the system */ /*package*/ Event(byte[] data) { @@ -106,7 +107,7 @@ public class EventLog { return mBuffer.getInt(offset); } - /** @return one of Integer, Long, String, null, or Object[] of same. */ + /** @return one of Integer, Long, Float, String, null, or Object[] of same. */ public synchronized Object getData() { try { int offset = mBuffer.getShort(HEADER_SIZE_OFFSET); @@ -130,10 +131,13 @@ public class EventLog { byte type = mBuffer.get(); switch (type) { case INT_TYPE: - return (Integer) mBuffer.getInt(); + return mBuffer.getInt(); case LONG_TYPE: - return (Long) mBuffer.getLong(); + return mBuffer.getLong(); + + case FLOAT_TYPE: + return mBuffer.getFloat(); case STRING_TYPE: try { @@ -180,6 +184,14 @@ public class EventLog { /** * Record an event log message. * @param tag The event type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeEvent(int tag, float value); + + /** + * Record an event log message. + * @param tag The event type tag code * @param str A value to log * @return The number of bytes written */ diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java index eedbc70..46dd857 100644 --- a/core/java/android/view/DisplayListCanvas.java +++ b/core/java/android/view/DisplayListCanvas.java @@ -234,25 +234,13 @@ public class DisplayListCanvas extends Canvas { * Draws the specified display list onto this canvas. The display list can only * be drawn if {@link android.view.RenderNode#isValid()} returns true. * - * @param renderNode The RenderNode to replay. + * @param renderNode The RenderNode to draw. */ public void drawRenderNode(RenderNode renderNode) { - drawRenderNode(renderNode, RenderNode.FLAG_CLIP_CHILDREN); + nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList()); } - /** - * Draws the specified display list onto this canvas. - * - * @param renderNode The RenderNode to replay. - * @param flags Optional flags about drawing, see {@link RenderNode} for - * the possible flags. - */ - public void drawRenderNode(RenderNode renderNode, int flags) { - nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList(), flags); - } - - private static native void nDrawRenderNode(long renderer, long renderNode, - int flags); + private static native void nDrawRenderNode(long renderer, long renderNode); /////////////////////////////////////////////////////////////////////////// // Hardware layer diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java index 794c8e7..a3e7a10 100644 --- a/core/java/android/view/PhoneWindow.java +++ b/core/java/android/view/PhoneWindow.java @@ -3599,7 +3599,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (!mForcedNavigationBarColor) { mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000); } - if (a.getBoolean(R.styleable.Window_windowHasLightStatusBar, false)) { + if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) { decor.setSystemUiVisibility( decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index ad34f02..6db46e9 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -284,11 +284,6 @@ public class TextureView extends View { return LAYER_TYPE_HARDWARE; } - @Override - boolean hasStaticLayer() { - return true; - } - /** * Calling this method has no effect. */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 7da2da4..b5b7f0f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -30,6 +30,7 @@ import android.annotation.Nullable; import android.annotation.Size; import android.content.ClipData; import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.Configuration; @@ -2591,7 +2592,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS * FLAG_TRANSLUCENT_STATUS}. * - * @see android.R.attr#windowHasLightStatusBar + * @see android.R.attr#windowLightStatusBar */ public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000; @@ -4016,37 +4017,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final String handlerName = a.getString(attr); if (handlerName != null) { - setOnClickListener(new OnClickListener() { - private Method mHandler; - - public void onClick(View v) { - if (mHandler == null) { - try { - mHandler = getContext().getClass().getMethod(handlerName, - View.class); - } catch (NoSuchMethodException e) { - int id = getId(); - String idText = id == NO_ID ? "" : " with id '" - + getContext().getResources().getResourceEntryName( - id) + "'"; - throw new IllegalStateException("Could not find a method " + - handlerName + "(View) in the activity " - + getContext().getClass() + " for onClick handler" - + " on view " + View.this.getClass() + idText, e); - } - } - - try { - mHandler.invoke(getContext(), View.this); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Could not execute non " - + "public method of the activity", e); - } catch (InvocationTargetException e) { - throw new IllegalStateException("Could not execute " - + "method of the activity", e); - } - } - }); + setOnClickListener(new DeclaredOnClickListener(this, handlerName)); } break; case R.styleable.View_overScrollMode: @@ -4238,6 +4209,66 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * An implementation of OnClickListener that attempts to lazily load a + * named click handling method from a parent or ancestor context. + */ + private static class DeclaredOnClickListener implements OnClickListener { + private final View mHostView; + private final String mMethodName; + + private Method mMethod; + + public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) { + mHostView = hostView; + mMethodName = methodName; + } + + @Override + public void onClick(@NonNull View v) { + if (mMethod == null) { + mMethod = resolveMethod(mHostView.getContext(), mMethodName); + } + + try { + mMethod.invoke(mHostView.getContext(), v); + } catch (IllegalAccessException e) { + throw new IllegalStateException( + "Could not execute non-public method for android:onClick", e); + } catch (InvocationTargetException e) { + throw new IllegalStateException( + "Could not execute method for android:onClick", e); + } + } + + @NonNull + private Method resolveMethod(@Nullable Context context, @NonNull String name) { + while (context != null) { + try { + if (!context.isRestricted()) { + return context.getClass().getMethod(mMethodName, View.class); + } + } catch (NoSuchMethodException e) { + // Failed to find method, keep searching up the hierarchy. + } + + if (context instanceof ContextWrapper) { + context = ((ContextWrapper) context).getBaseContext(); + } else { + // Can't search up the hierarchy, null out and fail. + context = null; + } + } + + final int id = mHostView.getId(); + final String idText = id == NO_ID ? "" : " with id '" + + mHostView.getContext().getResources().getResourceEntryName(id) + "'"; + throw new IllegalStateException("Could not find method " + mMethodName + + "(View) in a parent or ancestor Context for android:onClick " + + "attribute defined on view " + mHostView.getClass() + idText); + } + } + + /** * Non-public constructor for use in testing */ View() { @@ -14342,15 +14373,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Indicates whether this view has a static layer. A view with layer type - * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are - * dynamic. - */ - boolean hasStaticLayer() { - return true; - } - - /** * Indicates what type of layer is currently associated with this view. By default * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} @@ -15468,12 +15490,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (drawingWithRenderNode) { renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); } else if (layerType == LAYER_TYPE_NONE) { - int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; - if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0) { - layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; - } canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), - multipliedAlpha, layerFlags); + multipliedAlpha); } } else { // Alpha is handled by the child directly, clobber the layer's alpha @@ -15509,7 +15527,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (!drawingWithDrawingCache) { if (drawingWithRenderNode) { mPrivateFlags &= ~PFLAG_DIRTY_MASK; - ((DisplayListCanvas) canvas).drawRenderNode(renderNode, parentFlags); + ((DisplayListCanvas) canvas).drawRenderNode(renderNode); } else { // Fast path for layouts with no backgrounds if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 4324e75..d0d4201 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3505,8 +3505,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final View[] children = mChildren; for (int i = 0; i < count; i++) { final View child = children[i]; - if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) && - child.hasStaticLayer()) { + if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null)) { recreateChildDisplayList(child); } } diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java index 478fa00..d271af2 100644 --- a/core/java/android/widget/DayPickerPagerAdapter.java +++ b/core/java/android/widget/DayPickerPagerAdapter.java @@ -286,14 +286,10 @@ class DayPickerPagerAdapter extends PagerAdapter { return null; } - private boolean isCalendarInRange(Calendar value) { - return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0; - } - private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() { @Override public void onDayClick(SimpleMonthView view, Calendar day) { - if (day != null && isCalendarInRange(day)) { + if (day != null) { setSelectedDay(day); if (mOnDaySelectedListener != null) { diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index 113e597..334afab 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -178,6 +178,13 @@ class DayPickerView extends ViewGroup { }); } + private void updateButtonVisibility(int position) { + final boolean hasPrev = position > 0; + final boolean hasNext = position < (mAdapter.getCount() - 1); + mPrevButton.setVisibility(hasPrev ? View.VISIBLE : View.INVISIBLE); + mNextButton.setVisibility(hasNext ? View.VISIBLE : View.INVISIBLE); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final ViewPager viewPager = mViewPager; @@ -218,12 +225,6 @@ class DayPickerView extends ViewGroup { final int height = bottom - top; mViewPager.layout(0, 0, width, height); - if (mViewPager.getChildCount() < 1) { - leftButton.setVisibility(View.INVISIBLE); - rightButton.setVisibility(View.INVISIBLE); - return; - } - final SimpleMonthView monthView = (SimpleMonthView) mViewPager.getChildAt(0); final int monthHeight = monthView.getMonthHeight(); final int cellWidth = monthView.getCellWidth(); @@ -235,7 +236,6 @@ class DayPickerView extends ViewGroup { final int leftIconTop = monthView.getPaddingTop() + (monthHeight - leftDH) / 2; final int leftIconLeft = monthView.getPaddingLeft() + (cellWidth - leftDW) / 2; leftButton.layout(leftIconLeft, leftIconTop, leftIconLeft + leftDW, leftIconTop + leftDH); - leftButton.setVisibility(View.VISIBLE); final int rightDW = rightButton.getMeasuredWidth(); final int rightDH = rightButton.getMeasuredHeight(); @@ -243,7 +243,6 @@ class DayPickerView extends ViewGroup { final int rightIconRight = width - monthView.getPaddingRight() - (cellWidth - rightDW) / 2; rightButton.layout(rightIconRight - rightDW, rightIconTop, rightIconRight, rightIconTop + rightDH); - rightButton.setVisibility(View.VISIBLE); } public void setDayOfWeekTextAppearance(int resId) { @@ -399,10 +398,7 @@ class DayPickerView extends ViewGroup { @Override public void onPageSelected(int position) { - mPrevButton.setVisibility( - position > 0 ? View.VISIBLE : View.INVISIBLE); - mNextButton.setVisibility( - position < (mAdapter.getCount() - 1) ? View.VISIBLE : View.INVISIBLE); + updateButtonVisibility(position); } }; diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 39b9907..35e7389 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -62,7 +62,6 @@ import android.text.TextUtils; import android.text.method.KeyListener; import android.text.method.MetaKeyKeyListener; import android.text.method.MovementMethod; -import android.text.method.PasswordTransformationMethod; import android.text.method.WordIterator; import android.text.style.EasyEditSpan; import android.text.style.SuggestionRangeSpan; @@ -145,16 +144,16 @@ public class Editor { InputContentType mInputContentType; InputMethodState mInputMethodState; - private static class TextDisplayList { - RenderNode displayList; + private static class TextRenderNode { + RenderNode renderNode; boolean isDirty; - public TextDisplayList(String name) { + public TextRenderNode(String name) { isDirty = true; - displayList = RenderNode.create(name, null); + renderNode = RenderNode.create(name, null); } - boolean needsRecord() { return isDirty || !displayList.isValid(); } + boolean needsRecord() { return isDirty || !renderNode.isValid(); } } - TextDisplayList[] mTextDisplayLists; + TextRenderNode[] mTextRenderNodes; boolean mFrozenWithFocus; boolean mSelectionMoved; @@ -360,10 +359,10 @@ public class Editor { } private void destroyDisplayListsData() { - if (mTextDisplayLists != null) { - for (int i = 0; i < mTextDisplayLists.length; i++) { - RenderNode displayList = mTextDisplayLists[i] != null - ? mTextDisplayLists[i].displayList : null; + if (mTextRenderNodes != null) { + for (int i = 0; i < mTextRenderNodes.length; i++) { + RenderNode displayList = mTextRenderNodes[i] != null + ? mTextRenderNodes[i].renderNode : null; if (displayList != null && displayList.isValid()) { displayList.destroyDisplayListData(); } @@ -682,34 +681,6 @@ public class Editor { } } - /** - * Unlike {@link TextView#textCanBeSelected()}, this method is based on the <i>current</i> state - * of the TextView. textCanBeSelected() has to be true (this is one of the conditions to have - * a selection controller (see {@link #prepareCursorControllers()}), but this is not sufficient. - */ - private boolean canSelectText() { - return hasSelectionController() && mTextView.getText().length() != 0; - } - - /** - * It would be better to rely on the input type for everything. A password inputType should have - * a password transformation. We should hence use isPasswordInputType instead of this method. - * - * We should: - * - Call setInputType in setKeyListener instead of changing the input type directly (which - * would install the correct transformation). - * - Refuse the installation of a non-password transformation in setTransformation if the input - * type is password. - * - * However, this is like this for legacy reasons and we cannot break existing apps. This method - * is useful since it matches what the user can see (obfuscated text or not). - * - * @return true if the current transformation method is of the password type. - */ - private boolean hasPasswordTransformationMethod() { - return mTextView.getTransformationMethod() instanceof PasswordTransformationMethod; - } - private int getWordStart(int offset) { // FIXME - For this and similar methods we're not doing anything to check if there's // a LocaleSpan in the text, this may be something we should try handling or checking for. @@ -758,11 +729,11 @@ public class Editor { * successfully performed. */ private boolean selectCurrentWord() { - if (!canSelectText()) { + if (!mTextView.canSelectText()) { return false; } - if (hasPasswordTransformationMethod()) { + if (mTextView.hasPasswordTransformationMethod()) { // Always select all on a password field. // Cut/copy menu entries are not available for passwords, but being able to select all // is however useful to delete or paste to replace the entire content. @@ -1467,8 +1438,8 @@ public class Editor { firstLine, lastLine); if (layout instanceof DynamicLayout) { - if (mTextDisplayLists == null) { - mTextDisplayLists = ArrayUtils.emptyArray(TextDisplayList.class); + if (mTextRenderNodes == null) { + mTextRenderNodes = ArrayUtils.emptyArray(TextRenderNode.class); } DynamicLayout dynamicLayout = (DynamicLayout) layout; @@ -1489,19 +1460,19 @@ public class Editor { searchStartIndex); // Note how dynamic layout's internal block indices get updated from Editor blockIndices[i] = blockIndex; - if (mTextDisplayLists[blockIndex] != null) { - mTextDisplayLists[blockIndex].isDirty = true; + if (mTextRenderNodes[blockIndex] != null) { + mTextRenderNodes[blockIndex].isDirty = true; } searchStartIndex = blockIndex + 1; } - if (mTextDisplayLists[blockIndex] == null) { - mTextDisplayLists[blockIndex] = - new TextDisplayList("Text " + blockIndex); + if (mTextRenderNodes[blockIndex] == null) { + mTextRenderNodes[blockIndex] = + new TextRenderNode("Text " + blockIndex); } - final boolean blockDisplayListIsInvalid = mTextDisplayLists[blockIndex].needsRecord(); - RenderNode blockDisplayList = mTextDisplayLists[blockIndex].displayList; + final boolean blockDisplayListIsInvalid = mTextRenderNodes[blockIndex].needsRecord(); + RenderNode blockDisplayList = mTextRenderNodes[blockIndex].renderNode; if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) { final int blockBeginLine = endOfPreviousBlock + 1; final int top = layout.getLineTop(blockBeginLine); @@ -1528,7 +1499,7 @@ public class Editor { // brings this range of text back to the top left corner of the viewport displayListCanvas.translate(-left, -top); layout.drawText(displayListCanvas, blockBeginLine, blockEndLine); - mTextDisplayLists[blockIndex].isDirty = false; + mTextRenderNodes[blockIndex].isDirty = false; // No need to untranslate, previous context is popped after // drawDisplayList } finally { @@ -1543,8 +1514,7 @@ public class Editor { blockDisplayList.setLeftTopRightBottom(left, top, right, bottom); } - ((DisplayListCanvas) canvas).drawRenderNode(blockDisplayList, - 0 /* no child clipping, our TextView parent enforces it */); + ((DisplayListCanvas) canvas).drawRenderNode(blockDisplayList); endOfPreviousBlock = blockEndLine; } @@ -1558,7 +1528,7 @@ public class Editor { private int getAvailableDisplayListIndex(int[] blockIndices, int numberOfBlocks, int searchStartIndex) { - int length = mTextDisplayLists.length; + int length = mTextRenderNodes.length; for (int i = searchStartIndex; i < length; i++) { boolean blockIndexFound = false; for (int j = 0; j < numberOfBlocks; j++) { @@ -1572,7 +1542,7 @@ public class Editor { } // No available index found, the pool has to grow - mTextDisplayLists = GrowingArrayUtils.append(mTextDisplayLists, length, null); + mTextRenderNodes = GrowingArrayUtils.append(mTextRenderNodes, length, null); return length; } @@ -1589,7 +1559,7 @@ public class Editor { * Invalidates all the sub-display lists that overlap the specified character range */ void invalidateTextDisplayList(Layout layout, int start, int end) { - if (mTextDisplayLists != null && layout instanceof DynamicLayout) { + if (mTextRenderNodes != null && layout instanceof DynamicLayout) { final int firstLine = layout.getLineForOffset(start); final int lastLine = layout.getLineForOffset(end); @@ -1609,7 +1579,7 @@ public class Editor { while (i < numberOfBlocks) { final int blockIndex = blockIndices[i]; if (blockIndex != DynamicLayout.INVALID_BLOCK_INDEX) { - mTextDisplayLists[blockIndex].isDirty = true; + mTextRenderNodes[blockIndex].isDirty = true; } if (blockEndLines[i] >= lastLine) break; i++; @@ -1618,9 +1588,9 @@ public class Editor { } void invalidateTextDisplayList() { - if (mTextDisplayLists != null) { - for (int i = 0; i < mTextDisplayLists.length; i++) { - if (mTextDisplayLists[i] != null) mTextDisplayLists[i].isDirty = true; + if (mTextRenderNodes != null) { + for (int i = 0; i < mTextRenderNodes.length; i++) { + if (mTextRenderNodes[i] != null) mTextRenderNodes[i].isDirty = true; } } } @@ -1718,7 +1688,7 @@ public class Editor { return false; } - if (!canSelectText() || !mTextView.requestFocus()) { + if (!mTextView.canSelectText() || !mTextView.requestFocus()) { Log.w(TextView.LOG_TAG, "TextView does not support text selection. Action mode cancelled."); return false; @@ -3090,7 +3060,7 @@ public class Editor { MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } - if (canSelectText() && !hasPasswordTransformationMethod()) { + if (mTextView.canSelectAllText()) { menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll). setAlphabeticShortcut('a'). setShowAsAction( @@ -3847,6 +3817,10 @@ public class Editor { startSelectionActionModeWithoutSelection(); } } + } else { + if (mSelectionActionMode != null) { + mSelectionActionMode.invalidateContentRect(); + } } hideAfterDelay(); break; @@ -4491,7 +4465,7 @@ public class Editor { private class CorrectionHighlighter { private final Path mPath = new Path(); - private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint mPaint = new Paint(); private int mStart, mEnd; private long mFadingStartTime; private RectF mTempRectF; diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index 2778f0f..acf1df9 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -31,6 +31,7 @@ import android.text.TextPaint; import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.IntArray; +import android.util.MathUtils; import android.util.StateSet; import android.view.MotionEvent; import android.view.View; @@ -422,7 +423,8 @@ class SimpleMonthView extends View { int stateMask = 0; - if (day >= mEnabledDayStart && day <= mEnabledDayEnd) { + final boolean isDayEnabled = isDayEnabled(day); + if (isDayEnabled) { stateMask |= StateSet.VIEW_STATE_ENABLED; } @@ -435,8 +437,11 @@ class SimpleMonthView extends View { } else if (mTouchedItem == day) { stateMask |= StateSet.VIEW_STATE_PRESSED; - // Adjust the circle to be centered on the row. - canvas.drawCircle(colCenterRtl, rowCenter, mDaySelectorRadius, mDayHighlightPaint); + if (isDayEnabled) { + // Adjust the circle to be centered on the row. + canvas.drawCircle(colCenterRtl, rowCenter, + mDaySelectorRadius, mDayHighlightPaint); + } } final boolean isDayToday = mToday == day; @@ -460,6 +465,14 @@ class SimpleMonthView extends View { } } + private boolean isDayEnabled(int day) { + return day >= mEnabledDayStart && day <= mEnabledDayEnd; + } + + private boolean isValidDayOfMonth(int day) { + return day >= 1 && day <= mDaysInMonth; + } + private static boolean isValidDayOfWeek(int day) { return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY; } @@ -536,13 +549,6 @@ class SimpleMonthView extends View { mWeekStart = mCalendar.getFirstDayOfWeek(); } - if (enabledDayStart > 0 && enabledDayEnd < 32) { - mEnabledDayStart = enabledDayStart; - } - if (enabledDayEnd > 0 && enabledDayEnd < 32 && enabledDayEnd >= enabledDayStart) { - mEnabledDayEnd = enabledDayEnd; - } - // Figure out what day today is. final Calendar today = Calendar.getInstance(); mToday = -1; @@ -554,6 +560,9 @@ class SimpleMonthView extends View { } } + mEnabledDayStart = MathUtils.constrain(enabledDayStart, 1, mDaysInMonth); + mEnabledDayEnd = MathUtils.constrain(enabledDayEnd, mEnabledDayStart, mDaysInMonth); + // Invalidate the old title. mTitle = null; @@ -694,7 +703,7 @@ class SimpleMonthView extends View { final int col = (paddedXRtl * DAYS_IN_WEEK) / mPaddedWidth; final int index = col + row * DAYS_IN_WEEK; final int day = index + 1 - findDayOffset(); - if (day < 1 || day > mDaysInMonth) { + if (!isValidDayOfMonth(day)) { return -1; } @@ -708,7 +717,7 @@ class SimpleMonthView extends View { * @param outBounds the rect to populate with bounds */ private boolean getBoundsForDay(int id, Rect outBounds) { - if (id < 1 || id > mDaysInMonth) { + if (!isValidDayOfMonth(id)) { return false; } @@ -742,7 +751,7 @@ class SimpleMonthView extends View { * @param day the day that was clicked */ private boolean onDayClicked(int day) { - if (day < 0 || day > mDaysInMonth) { + if (!isValidDayOfMonth(day) || !isDayEnabled(day)) { return false; } @@ -774,7 +783,7 @@ class SimpleMonthView extends View { @Override protected int getVirtualViewAt(float x, float y) { final int day = getDayAtLocation((int) (x + 0.5f), (int) (y + 0.5f)); - if (day >= 0) { + if (day != -1) { return day; } return ExploreByTouchHelper.INVALID_ID; @@ -808,7 +817,13 @@ class SimpleMonthView extends View { node.setText(getDayText(virtualViewId)); node.setContentDescription(getDayDescription(virtualViewId)); node.setBoundsInParent(mTempRect); - node.addAction(AccessibilityAction.ACTION_CLICK); + + final boolean isDayEnabled = isDayEnabled(virtualViewId); + if (isDayEnabled) { + node.addAction(AccessibilityAction.ACTION_CLICK); + } + + node.setEnabled(isDayEnabled); if (virtualViewId == mActivatedDay) { // TODO: This should use activated once that's supported. @@ -835,7 +850,7 @@ class SimpleMonthView extends View { * @return a description of the virtual view */ private CharSequence getDayDescription(int id) { - if (id >= 1 && id <= mDaysInMonth) { + if (isValidDayOfMonth(id)) { mTempCalendar.set(mYear, mMonth, id); return DateFormat.format(DATE_FORMAT, mTempCalendar.getTimeInMillis()); } @@ -850,7 +865,7 @@ class SimpleMonthView extends View { * @return the visible text of the virtual view */ private CharSequence getDayText(int id) { - if (id >= 1 && id <= mDaysInMonth) { + if (isValidDayOfMonth(id)) { return Integer.toString(id); } diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index ae779fe..f94f97c 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -216,7 +216,7 @@ public class Switch extends CompoundButton { public Switch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + mTextPaint = new TextPaint(); final Resources res = getResources(); mTextPaint.density = res.getDisplayMetrics().density; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 3e8df08..774a864 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -668,11 +668,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final Resources res = getResources(); final CompatibilityInfo compat = res.getCompatibilityInfo(); - mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + mTextPaint = new TextPaint(); mTextPaint.density = res.getDisplayMetrics().density; mTextPaint.setCompatibilityScaling(compat.applicationScale); - mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mHighlightPaint = new Paint(); mHighlightPaint.setCompatibilityScaling(compat.applicationScale); mMovement = getDefaultMovementMethod(); @@ -4569,7 +4569,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @return true if the current transformation method is of the password type. */ - private boolean hasPasswordTransformationMethod() { + boolean hasPasswordTransformationMethod() { return mTransformation instanceof PasswordTransformationMethod; } @@ -8583,7 +8583,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * a selection controller (see {@link Editor#prepareCursorControllers()}), but this is not * sufficient. */ - private boolean canSelectText() { + boolean canSelectText() { return mText.length() != 0 && mEditor != null && mEditor.hasSelectionController(); } @@ -9199,6 +9199,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } + boolean canSelectAllText() { + return canSelectText() && !hasPasswordTransformationMethod(); + } + boolean selectAllText() { // Need to hide insert point cursor controller before settings selection, otherwise insert // point cursor controller obtains cursor update event and update cursor with cancelling |
