summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorScott Lobdell <slobdell@google.com>2021-04-10 00:27:34 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-04-10 00:27:34 +0000
commit01da99e3e562d93c902419316b2f6aa464777e16 (patch)
tree2fe6d242f8218ab669e2a98f757a85005ff88088 /core/java
parent80bf29781b44a4c22692a3a1a1e60a371471c25a (diff)
parent6560a5b465795d6922ccd0c83693fa04be2910a6 (diff)
Merge changes from topic "SP1A.210407.002" into s-keystone-qcom-dev
* changes: Adapt to new ranking logic from upstream. Revert "Initial data pipeline for Smartspace media recommendations data in media carousel." Merge SP1A.210407.002
Diffstat (limited to 'core/java')
-rw-r--r--core/java/Android.bp104
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java81
-rw-r--r--core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl3
-rw-r--r--core/java/android/app/Activity.java21
-rw-r--r--core/java/android/app/ActivityThread.java4
-rw-r--r--core/java/android/app/AppOpsManager.java75
-rw-r--r--core/java/android/app/AppOpsManagerInternal.java12
-rw-r--r--core/java/android/app/ContextImpl.java11
-rw-r--r--core/java/android/app/IActivityManager.aidl6
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/IUiAutomationConnection.aidl3
-rw-r--r--core/java/android/app/Notification.java189
-rw-r--r--core/java/android/app/NotificationHistory.java20
-rw-r--r--core/java/android/app/NotificationManager.java16
-rw-r--r--core/java/android/app/PendingIntent.java3
-rw-r--r--core/java/android/app/SyncNotedAppOp.java59
-rw-r--r--core/java/android/app/SystemServiceRegistry.java2
-rw-r--r--core/java/android/app/UiAutomation.java32
-rw-r--r--core/java/android/app/UiAutomationConnection.java17
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java43
-rw-r--r--core/java/android/app/assist/AssistStructure.java20
-rw-r--r--core/java/android/app/usage/IUsageStatsManager.aidl1
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java28
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java16
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeScanner.java17
-rw-r--r--core/java/android/content/AttributionSource.java17
-rw-r--r--core/java/android/content/Context.java1
-rw-r--r--core/java/android/content/ContextParams.java10
-rw-r--r--core/java/android/content/PermissionChecker.java4
-rw-r--r--core/java/android/content/pm/ActivityInfo.java7
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java15
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageImpl.java29
-rw-r--r--core/java/android/content/res/ColorStateList.java5
-rw-r--r--core/java/android/content/res/loader/ResourcesProvider.java5
-rw-r--r--core/java/android/content/rollback/RollbackManagerFrameworkInitializer.java2
-rw-r--r--core/java/android/graphics/fonts/FontFamilyUpdateRequest.java11
-rw-r--r--core/java/android/graphics/fonts/FontUpdateRequest.java319
-rw-r--r--core/java/android/hardware/biometrics/BiometricTestSession.java23
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java9
-rw-r--r--core/java/android/hardware/camera2/impl/CameraExtensionForwardProcessor.java13
-rw-r--r--core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java2
-rw-r--r--core/java/android/hardware/camera2/params/MandatoryStreamCombination.java83
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java7
-rw-r--r--core/java/android/inputmethodservice/ImsConfigurationTracker.java102
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java14
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl1
-rw-r--r--core/java/android/net/NetworkIdentity.java14
-rw-r--r--core/java/android/net/NetworkPolicyManager.java27
-rw-r--r--core/java/android/net/vcn/IVcnStatusCallback.aidl2
-rw-r--r--core/java/android/net/vcn/VcnConfig.java13
-rw-r--r--core/java/android/net/vcn/VcnGatewayConnectionConfig.java39
-rw-r--r--core/java/android/net/vcn/VcnManager.java21
-rw-r--r--core/java/android/os/BatteryConsumer.java56
-rw-r--r--core/java/android/os/BatteryUsageStats.java15
-rw-r--r--core/java/android/os/BatteryUsageStatsQuery.java17
-rwxr-xr-xcore/java/android/os/Build.java13
-rw-r--r--core/java/android/os/FileUtils.java41
-rw-r--r--core/java/android/os/PowerComponents.java37
-rw-r--r--core/java/android/os/SystemBatteryConsumer.java4
-rw-r--r--core/java/android/os/SystemVibratorManager.java10
-rw-r--r--core/java/android/os/UidBatteryConsumer.java4
-rw-r--r--core/java/android/os/UserBatteryConsumer.java5
-rw-r--r--core/java/android/os/incremental/IncrementalManager.java11
-rw-r--r--core/java/android/permission/IPermissionController.aidl6
-rw-r--r--core/java/android/permission/PermissionControllerManager.java44
-rw-r--r--core/java/android/permission/PermissionControllerService.java53
-rw-r--r--core/java/android/permission/PermissionManager.java1
-rw-r--r--core/java/android/provider/DeviceConfig.java16
-rw-r--r--core/java/android/provider/Settings.java8
-rw-r--r--core/java/android/security/ConfirmationPrompt.java180
-rw-r--r--core/java/android/security/keymaster/KeymasterCertificateChain.aidl19
-rw-r--r--core/java/android/security/keystore/recovery/RecoveryController.java16
-rw-r--r--core/java/android/service/notification/NotificationListenerFilter.java14
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java23
-rw-r--r--core/java/android/service/rotationresolver/RotationResolutionRequest.java12
-rw-r--r--core/java/android/speech/OWNERS3
-rw-r--r--core/java/android/speech/SpeechRecognizer.java24
-rw-r--r--core/java/android/text/method/TranslationTransformationMethod.java13
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/util/Slog.java27
-rw-r--r--core/java/android/util/TimeUtils.java33
-rw-r--r--core/java/android/uwb/RangingManager.java8
-rw-r--r--core/java/android/uwb/UwbManager.java31
-rw-r--r--core/java/android/view/HapticFeedbackConstants.java6
-rw-r--r--core/java/android/view/InputEventReceiver.java10
-rw-r--r--core/java/android/view/InputEventSender.java17
-rw-r--r--core/java/android/view/InsetsState.java14
-rw-r--r--core/java/android/view/OWNERS4
-rw-r--r--core/java/android/view/RemoteAnimationTarget.java23
-rw-r--r--core/java/android/view/Surface.java42
-rw-r--r--core/java/android/view/SurfaceControl.java27
-rw-r--r--core/java/android/view/SurfaceControlHdrLayerInfoListener.java102
-rw-r--r--core/java/android/view/View.java42
-rw-r--r--core/java/android/view/ViewGroup.java31
-rw-r--r--core/java/android/view/ViewRoot.java53
-rw-r--r--core/java/android/view/ViewRootImpl.java48
-rw-r--r--core/java/android/view/ViewStructure.java4
-rw-r--r--core/java/android/view/Window.java22
-rw-r--r--core/java/android/view/WindowManager.java30
-rw-r--r--core/java/android/view/accessibility/AccessibilityCache.java77
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java113
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java30
-rw-r--r--core/java/android/view/contentcapture/ViewNode.java16
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java4
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java3
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java51
-rw-r--r--core/java/android/view/translation/UiTranslationController.java27
-rw-r--r--core/java/android/view/translation/ViewTranslationRequest.java153
-rw-r--r--core/java/android/webkit/WebViewProvider.java1
-rwxr-xr-xcore/java/android/widget/AbsListView.java1
-rw-r--r--core/java/android/widget/EdgeEffect.java35
-rw-r--r--core/java/android/widget/TextView.java8
-rw-r--r--core/java/android/widget/TextViewOnReceiveContentListener.java2
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl8
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl2
-rw-r--r--core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl2
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java9
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java64
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java45
-rw-r--r--core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java15
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java169
-rw-r--r--core/java/com/android/internal/os/BatteryUsageStatsProvider.java9
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java32
-rw-r--r--core/java/com/android/internal/os/BinderLatencyObserver.java157
-rw-r--r--core/java/com/android/internal/os/BluetoothPowerCalculator.java33
-rw-r--r--core/java/com/android/internal/os/CpuPowerCalculator.java30
-rw-r--r--core/java/com/android/internal/os/DmabufInfoReader.java51
-rw-r--r--core/java/com/android/internal/os/GnssPowerCalculator.java56
-rw-r--r--core/java/com/android/internal/os/MobileRadioPowerCalculator.java68
-rw-r--r--core/java/com/android/internal/os/PowerCalculator.java43
-rw-r--r--core/java/com/android/internal/os/ScreenPowerCalculator.java102
-rw-r--r--core/java/com/android/internal/os/WifiPowerCalculator.java77
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java7
-rw-r--r--core/java/com/android/internal/os/ZygoteServer.java2
-rw-r--r--core/java/com/android/internal/policy/DecorView.java26
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java6
-rw-r--r--core/java/com/android/internal/view/IInputMethod.aidl3
-rw-r--r--core/java/com/android/internal/widget/RecyclerView.java20
139 files changed, 3012 insertions, 1354 deletions
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 2fdf9c146ff6..919f1e2e85fb 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -10,6 +10,15 @@ package {
}
filegroup {
+ name: "framework-core-sources",
+ srcs: [
+ "**/*.java",
+ "**/*.aidl",
+ ],
+ visibility: ["//frameworks/base"],
+}
+
+filegroup {
name: "IKeyAttestationApplicationIdProvider.aidl",
srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
}
@@ -23,3 +32,98 @@ filegroup {
name: "ITracingServiceProxy.aidl",
srcs: ["android/tracing/ITracingServiceProxy.aidl"],
}
+
+// These are subset of framework-core-sources that are needed by the
+// android.test.mock library. The implementation of android.test.mock references
+// private members of various components to allow mocking of classes that cannot
+// be mocked without access to those internal implementation details.
+filegroup {
+ name: "framework-core-sources-for-test-mock",
+ srcs: [
+ "android/accounts/AccountManagerCallback.java",
+ "android/accounts/AccountManagerFuture.java",
+ "android/accounts/AccountManager.java",
+ "android/accounts/AccountsException.java",
+ "android/accounts/AuthenticatorException.java",
+ "android/accounts/OperationCanceledException.java",
+ "android/annotation/AnimatorRes.java",
+ "android/annotation/AnimRes.java",
+ "android/annotation/AnyRes.java",
+ "android/annotation/ArrayRes.java",
+ "android/annotation/AttrRes.java",
+ "android/annotation/BoolRes.java",
+ "android/annotation/BroadcastBehavior.java",
+ "android/annotation/CallbackExecutor.java",
+ "android/annotation/CallSuper.java",
+ "android/annotation/CheckResult.java",
+ "android/annotation/ColorInt.java",
+ "android/annotation/ColorRes.java",
+ "android/annotation/DimenRes.java",
+ "android/annotation/DrawableRes.java",
+ "android/annotation/FontRes.java",
+ "android/annotation/FractionRes.java",
+ "android/annotation/IntDef.java",
+ "android/annotation/IntegerRes.java",
+ "android/annotation/IntRange.java",
+ "android/annotation/LayoutRes.java",
+ "android/annotation/NonNull.java",
+ "android/annotation/Nullable.java",
+ "android/annotation/PluralsRes.java",
+ "android/annotation/RawRes.java",
+ "android/annotation/RequiresPermission.java",
+ "android/annotation/SdkConstant.java",
+ "android/annotation/Size.java",
+ "android/annotation/StringDef.java",
+ "android/annotation/StringRes.java",
+ "android/annotation/StyleableRes.java",
+ "android/annotation/StyleRes.java",
+ "android/annotation/SuppressLint.java",
+ "android/annotation/SystemApi.java",
+ "android/annotation/SystemService.java",
+ "android/annotation/TestApi.java",
+ "android/annotation/UserIdInt.java",
+ "android/annotation/XmlRes.java",
+ "android/app/Application.java",
+ "android/app/IApplicationThread.aidl",
+ "android/app/IServiceConnection.aidl",
+ "android/app/PackageDeleteObserver.java",
+ "android/content/ComponentCallbacks2.java",
+ "android/content/ComponentCallbacks.java",
+ "android/content/ContentInterface.java",
+ "android/content/ContentProvider.java",
+ "android/content/ContentProviderNative.java",
+ "android/content/ContentResolver.java",
+ "android/content/Context.java",
+ "android/content/ContextWrapper.java",
+ "android/content/DialogInterface.java",
+ "android/content/IContentProvider.java",
+ "android/content/Intent.java",
+ "android/content/IntentSender.java",
+ "android/content/OperationApplicationException.java",
+ "android/content/pm/ActivityInfo.java",
+ "android/content/pm/ApplicationInfo.java",
+ "android/content/pm/InstantAppInfo.java",
+ "android/content/pm/IPackageDataObserver.aidl",
+ "android/content/pm/KeySet.java",
+ "android/content/pm/PackageManager.java",
+ "android/content/pm/VerifierDeviceIdentity.java",
+ "android/content/res/Resources.java",
+ "android/database/CrossProcessCursor.java",
+ "android/database/CrossProcessCursorWrapper.java",
+ "android/database/Cursor.java",
+ "android/database/CursorWrapper.java",
+ "android/os/Binder.java",
+ "android/os/Bundle.java",
+ "android/os/IBinder.java",
+ "android/os/IInterface.java",
+ "android/os/Parcelable.java",
+ "android/os/ParcelFileDescriptor.java",
+ "android/os/RemoteException.java",
+ "android/os/storage/VolumeInfo.java",
+ "android/util/AndroidException.java",
+ "android/view/DisplayAdjustments.java",
+ "android/view/ViewDebug.java",
+ "com/android/internal/annotations/VisibleForTesting.java",
+ ],
+ visibility: ["//frameworks/base/test-mock"],
+}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index d5368213be08..483defab43c9 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -886,7 +886,7 @@ public abstract class AccessibilityService extends Service {
* them, otherwise an empty list.
*/
public List<AccessibilityWindowInfo> getWindows() {
- return AccessibilityInteractionClient.getInstance().getWindows(mConnectionId);
+ return AccessibilityInteractionClient.getInstance(this).getWindows(mConnectionId);
}
/**
@@ -914,7 +914,8 @@ public abstract class AccessibilityService extends Service {
*/
@NonNull
public final SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
- return AccessibilityInteractionClient.getInstance().getWindowsOnAllDisplays(mConnectionId);
+ return AccessibilityInteractionClient.getInstance(this).getWindowsOnAllDisplays(
+ mConnectionId);
}
/**
@@ -940,7 +941,8 @@ public abstract class AccessibilityService extends Service {
* @return The root node if this service can retrieve window content.
*/
public AccessibilityNodeInfo getRootInActiveWindow() {
- return AccessibilityInteractionClient.getInstance().getRootInActiveWindow(mConnectionId);
+ return AccessibilityInteractionClient.getInstance(this).getRootInActiveWindow(
+ mConnectionId);
}
/**
@@ -949,7 +951,7 @@ public abstract class AccessibilityService extends Service {
*/
public final void disableSelf() {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.disableSelf();
@@ -970,7 +972,7 @@ public abstract class AccessibilityService extends Service {
private void setDefaultTokenInternal(Context context, int displayId) {
final WindowManagerImpl wm = (WindowManagerImpl) context.getSystemService(WINDOW_SERVICE);
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
IBinder token = null;
if (connection != null) {
synchronized (mLock) {
@@ -1042,7 +1044,7 @@ public abstract class AccessibilityService extends Service {
public final @NonNull FingerprintGestureController getFingerprintGestureController() {
if (mFingerprintGestureController == null) {
mFingerprintGestureController = new FingerprintGestureController(
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId));
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId));
}
return mFingerprintGestureController;
}
@@ -1074,8 +1076,7 @@ public abstract class AccessibilityService extends Service {
@Nullable GestureResultCallback callback,
@Nullable Handler handler) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
- mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection == null) {
return false;
}
@@ -1287,7 +1288,7 @@ public abstract class AccessibilityService extends Service {
private void setMagnificationCallbackEnabled(boolean enabled) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1348,7 +1349,7 @@ public abstract class AccessibilityService extends Service {
*/
public float getScale() {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1377,7 +1378,7 @@ public abstract class AccessibilityService extends Service {
*/
public float getCenterX() {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1406,7 +1407,7 @@ public abstract class AccessibilityService extends Service {
*/
public float getCenterY() {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1440,7 +1441,7 @@ public abstract class AccessibilityService extends Service {
@NonNull
public Region getMagnificationRegion() {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1469,7 +1470,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean reset(boolean animate) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1497,7 +1498,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean setScale(float scale, boolean animate) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1529,7 +1530,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean setCenter(float centerX, float centerY, boolean animate) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1701,7 +1702,7 @@ public abstract class AccessibilityService extends Service {
private void setSoftKeyboardCallbackEnabled(boolean enabled) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1760,7 +1761,7 @@ public abstract class AccessibilityService extends Service {
@SoftKeyboardShowMode
public int getShowMode() {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1789,7 +1790,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1835,7 +1836,7 @@ public abstract class AccessibilityService extends Service {
*/
public boolean switchToInputMethod(@NonNull String imeId) {
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
+ AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
@@ -1888,7 +1889,7 @@ public abstract class AccessibilityService extends Service {
displayId);
if (controller == null) {
controller = new AccessibilityButtonController(
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId));
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId));
mAccessibilityButtonControllers.put(displayId, controller);
}
return controller;
@@ -1922,7 +1923,7 @@ public abstract class AccessibilityService extends Service {
*/
public final @NonNull List<AccessibilityAction> getSystemActions() {
IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
return connection.getSystemActions();
@@ -1955,7 +1956,7 @@ public abstract class AccessibilityService extends Service {
*/
public final boolean performGlobalAction(int action) {
IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
return connection.performGlobalAction(action);
@@ -1996,7 +1997,7 @@ public abstract class AccessibilityService extends Service {
* @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
*/
public AccessibilityNodeInfo findFocus(int focus) {
- return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
+ return AccessibilityInteractionClient.getInstance(this).findFocus(mConnectionId,
AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
}
@@ -2012,7 +2013,7 @@ public abstract class AccessibilityService extends Service {
*/
public final AccessibilityServiceInfo getServiceInfo() {
IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
return connection.getServiceInfo();
@@ -2044,12 +2045,12 @@ public abstract class AccessibilityService extends Service {
*/
private void sendServiceInfo() {
IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (mInfo != null && connection != null) {
try {
connection.setServiceInfo(mInfo);
mInfo = null;
- AccessibilityInteractionClient.getInstance().clearCache();
+ AccessibilityInteractionClient.getInstance(this).clearCache();
} catch (RemoteException re) {
Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
re.rethrowFromSystemServer();
@@ -2096,8 +2097,7 @@ public abstract class AccessibilityService extends Service {
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(
- mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection == null) {
sendScreenshotFailure(ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, executor, callback);
return;
@@ -2136,7 +2136,7 @@ public abstract class AccessibilityService extends Service {
*/
public void setAccessibilityFocusAppearance(int strokeWidth, @ColorInt int color) {
IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.setFocusAppearance(strokeWidth, color);
@@ -2261,12 +2261,14 @@ public abstract class AccessibilityService extends Service {
private final HandlerCaller mCaller;
private final Callbacks mCallback;
+ private final Context mContext;
private int mConnectionId = AccessibilityInteractionClient.NO_ID;
public IAccessibilityServiceClientWrapper(Context context, Looper looper,
Callbacks callback) {
mCallback = callback;
+ mContext = context;
mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/);
}
@@ -2366,7 +2368,8 @@ public abstract class AccessibilityService extends Service {
boolean serviceWantsEvent = message.arg1 != 0;
if (event != null) {
// Send the event to AccessibilityCache via AccessibilityInteractionClient
- AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event);
+ AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
+ event);
if (serviceWantsEvent
&& (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
// Send the event to AccessibilityService
@@ -2395,15 +2398,15 @@ public abstract class AccessibilityService extends Service {
IBinder windowToken = (IBinder) args.arg2;
args.recycle();
if (connection != null) {
- AccessibilityInteractionClient.getInstance().addConnection(mConnectionId,
- connection);
+ AccessibilityInteractionClient.getInstance(mContext).addConnection(
+ mConnectionId, connection);
mCallback.init(mConnectionId, windowToken);
mCallback.onServiceConnected();
} else {
- AccessibilityInteractionClient.getInstance().removeConnection(
+ AccessibilityInteractionClient.getInstance(mContext).removeConnection(
mConnectionId);
mConnectionId = AccessibilityInteractionClient.NO_ID;
- AccessibilityInteractionClient.getInstance().clearCache();
+ AccessibilityInteractionClient.getInstance(mContext).clearCache();
mCallback.init(AccessibilityInteractionClient.NO_ID, null);
}
return;
@@ -2415,14 +2418,14 @@ public abstract class AccessibilityService extends Service {
return;
}
case DO_CLEAR_ACCESSIBILITY_CACHE: {
- AccessibilityInteractionClient.getInstance().clearCache();
+ AccessibilityInteractionClient.getInstance(mContext).clearCache();
return;
}
case DO_ON_KEY_EVENT: {
KeyEvent event = (KeyEvent) message.obj;
try {
IAccessibilityServiceConnection connection = AccessibilityInteractionClient
- .getInstance().getConnection(mConnectionId);
+ .getInstance(mContext).getConnection(mConnectionId);
if (connection != null) {
final boolean result = mCallback.onKeyEvent(event);
final int sequence = message.arg1;
@@ -2637,7 +2640,7 @@ public abstract class AccessibilityService extends Service {
public void setGestureDetectionPassthroughRegion(int displayId, @NonNull Region region) {
Preconditions.checkNotNull(region, "region cannot be null");
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.setGestureDetectionPassthroughRegion(displayId, region);
@@ -2663,7 +2666,7 @@ public abstract class AccessibilityService extends Service {
public void setTouchExplorationPassthroughRegion(int displayId, @NonNull Region region) {
Preconditions.checkNotNull(region, "region cannot be null");
final IAccessibilityServiceConnection connection =
- AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (connection != null) {
try {
connection.setTouchExplorationPassthroughRegion(displayId, region);
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index ab21dc9f14ad..923b6f41414a 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -117,4 +117,7 @@ interface IAccessibilityServiceConnection {
void setTouchExplorationPassthroughRegion(int displayId, in Region region);
void setFocusAppearance(int strokeWidth, int color);
+
+ oneway void logTrace(long timestamp, String where, String callingParams, int processId,
+ long threadId, int callingUid, in Bundle serializedCallingStackInBundle);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0f38b5fdb5c3..f0d5a893bb96 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5254,32 +5254,17 @@ public class Activity extends ContextThemeWrapper
return;
}
- List<String> filteredPermissions = null;
-
if (!getAttributionSource().getRenouncedPermissions().isEmpty()) {
final int permissionCount = permissions.length;
for (int i = 0; i < permissionCount; i++) {
if (getAttributionSource().getRenouncedPermissions().contains(permissions[i])) {
- if (filteredPermissions == null) {
- filteredPermissions = new ArrayList<>(i);
- for (int j = 0; j < i; j++) {
- filteredPermissions.add(permissions[i]);
- }
- }
- } else if (filteredPermissions != null) {
- filteredPermissions.add(permissions[i]);
+ throw new IllegalArgumentException("Cannot request renounced permission: "
+ + permissions[i]);
}
}
}
- final Intent intent;
- if (filteredPermissions == null) {
- intent = getPackageManager().buildRequestPermissionsIntent(permissions);
- } else {
- intent = getPackageManager().buildRequestPermissionsIntent(
- filteredPermissions.toArray(new String[0]));
- }
-
+ final Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index df0fdfa00d06..2aa3e1ef2590 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4804,6 +4804,10 @@ public final class ActivityThread extends ClientTransactionHandler
}
if (r.isTopResumedActivity == onTop) {
+ if (!Build.IS_DEBUGGABLE) {
+ Slog.w(TAG, "Activity top position already set to onTop=" + onTop);
+ return;
+ }
throw new IllegalStateException("Activity top position already set to onTop=" + onTop);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 6ce0b2283603..436007cae502 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -33,6 +33,7 @@ import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -50,7 +51,6 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
-import android.content.AttributionSource;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -1223,8 +1223,11 @@ public class AppOpsManager {
public static final int OP_MANAGE_MEDIA = AppProtoEnums.APP_OP_MANAGE_MEDIA;
/** @hide */
+ public static final int OP_UWB_RANGING = AppProtoEnums.APP_OP_UWB_RANGING;
+
+ /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 112;
+ public static final int _NUM_OP = 113;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1637,6 +1640,8 @@ public class AppOpsManager {
* @hide
*/
public static final String OPSTR_MANAGE_MEDIA = "android:manage_media";
+ /** @hide */
+ public static final String OPSTR_UWB_RANGING = "android:uwb_ranging";
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
@@ -1706,6 +1711,7 @@ public class AppOpsManager {
// Nearby devices
OP_BLUETOOTH_SCAN,
OP_BLUETOOTH_CONNECT,
+ OP_UWB_RANGING,
// APPOP PERMISSIONS
OP_ACCESS_NOTIFICATIONS,
@@ -1846,6 +1852,7 @@ public class AppOpsManager {
OP_COARSE_LOCATION, // OP_COARSE_LOCATION_SOURCE
OP_MANAGE_MEDIA, // MANAGE_MEDIA
OP_BLUETOOTH_CONNECT, // OP_BLUETOOTH_CONNECT
+ OP_UWB_RANGING, // OP_UWB_RANGING
};
/**
@@ -1964,6 +1971,7 @@ public class AppOpsManager {
OPSTR_COARSE_LOCATION_SOURCE,
OPSTR_MANAGE_MEDIA,
OPSTR_BLUETOOTH_CONNECT,
+ OPSTR_UWB_RANGING,
};
/**
@@ -2083,6 +2091,7 @@ public class AppOpsManager {
"COARSE_LOCATION_SOURCE",
"MANAGE_MEDIA",
"BLUETOOTH_CONNECT",
+ "UWB_RANGING"
};
/**
@@ -2203,6 +2212,7 @@ public class AppOpsManager {
null, // no permission for OP_ACCESS_COARSE_LOCATION_SOURCE,
Manifest.permission.MANAGE_MEDIA,
Manifest.permission.BLUETOOTH_CONNECT,
+ Manifest.permission.UWB_RANGING,
};
/**
@@ -2323,6 +2333,7 @@ public class AppOpsManager {
null, // ACCESS_COARSE_LOCATION_SOURCE
null, // MANAGE_MEDIA
null, // BLUETOOTH_CONNECT
+ null, // UWB_RANGING
};
/**
@@ -2442,6 +2453,7 @@ public class AppOpsManager {
null, // ACCESS_COARSE_LOCATION_SOURCE
null, // MANAGE_MEDIA
null, // BLUETOOTH_CONNECT
+ null, // UWB_RANGING
};
/**
@@ -2560,6 +2572,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED, // ACCESS_COARSE_LOCATION_SOURCE
AppOpsManager.MODE_DEFAULT, // MANAGE_MEDIA
AppOpsManager.MODE_ALLOWED, // BLUETOOTH_CONNECT
+ AppOpsManager.MODE_ALLOWED, // UWB_RANGING
};
/**
@@ -2682,6 +2695,7 @@ public class AppOpsManager {
false, // ACCESS_COARSE_LOCATION_SOURCE
false, // MANAGE_MEDIA
false, // BLUETOOTH_CONNECT
+ false, // UWB_RANGING
};
/**
@@ -8015,18 +8029,18 @@ public class AppOpsManager {
}
}
- int mode = mService.noteOperation(op, uid, packageName, attributionTag,
+ SyncNotedAppOp syncOp = mService.noteOperation(op, uid, packageName, attributionTag,
collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
- if (mode == MODE_ALLOWED) {
+ if (syncOp.getOpMode()== MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op, attributionTag);
+ collectNotedOpForSelf(syncOp);
} else if (collectionMode == COLLECT_SYNC) {
- collectNotedOpSync(op, attributionTag);
+ collectNotedOpSync(syncOp);
}
}
- return mode;
+ return syncOp.getOpMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -8183,23 +8197,23 @@ public class AppOpsManager {
}
}
- int mode = mService.noteProxyOperation(op, attributionSource,
+ SyncNotedAppOp syncOp = mService.noteProxyOperation(op, attributionSource,
collectionMode == COLLECT_ASYNC, message,
shouldCollectMessage, skipProxyOperation);
- if (mode == MODE_ALLOWED) {
+ if (syncOp.getOpMode() == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op, attributionSource.getNextAttributionTag());
+ collectNotedOpForSelf(syncOp);
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
myUid) == PackageManager.PERMISSION_GRANTED ||
Binder.getCallingUid() == attributionSource.getNextUid())) {
- collectNotedOpSync(op, attributionSource.getNextAttributionTag());
+ collectNotedOpSync(syncOp);
}
}
- return mode;
+ return syncOp.getOpMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -8496,19 +8510,19 @@ public class AppOpsManager {
}
}
- int mode = mService.startOperation(getClientId(), op, uid, packageName,
+ SyncNotedAppOp syncOp = mService.startOperation(getClientId(), op, uid, packageName,
attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message,
shouldCollectMessage);
- if (mode == MODE_ALLOWED) {
+ if (syncOp.getOpMode() == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op, attributionTag);
+ collectNotedOpForSelf(syncOp);
} else if (collectionMode == COLLECT_SYNC) {
- collectNotedOpSync(op, attributionTag);
+ collectNotedOpSync(syncOp);
}
}
- return mode;
+ return syncOp.getOpMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -8611,24 +8625,23 @@ public class AppOpsManager {
}
}
- int mode = mService.startProxyOperation(getClientId(), op,
+ SyncNotedAppOp syncOp = mService.startProxyOperation(getClientId(), op,
attributionSource, false, collectionMode == COLLECT_ASYNC, message,
shouldCollectMessage, skipProxyOperation);
- if (mode == MODE_ALLOWED) {
+ if (syncOp.getOpMode() == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op,
- attributionSource.getNextAttributionTag());
+ collectNotedOpForSelf(syncOp);
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
Process.myUid()) == PackageManager.PERMISSION_GRANTED
|| Binder.getCallingUid() == attributionSource.getNextUid())) {
- collectNotedOpSync(op, attributionSource.getNextAttributionTag());
+ collectNotedOpSync(syncOp);
}
}
- return mode;
+ return syncOp.getOpMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -8869,13 +8882,13 @@ public class AppOpsManager {
* @param op The noted op
* @param attributionTag The attribution tag the op is noted for
*/
- private void collectNotedOpForSelf(int op, @Nullable String attributionTag) {
+ private void collectNotedOpForSelf(SyncNotedAppOp syncOp) {
synchronized (sLock) {
if (sOnOpNotedCallback != null) {
- sOnOpNotedCallback.onSelfNoted(new SyncNotedAppOp(op, attributionTag));
+ sOnOpNotedCallback.onSelfNoted(syncOp);
}
}
- sMessageCollector.onSelfNoted(new SyncNotedAppOp(op, attributionTag));
+ sMessageCollector.onSelfNoted(syncOp);
}
/**
@@ -8883,23 +8896,23 @@ public class AppOpsManager {
*
* <p> Delivered to caller via {@link #prefixParcelWithAppOpsIfNeeded}
*
- * @param op The noted op
- * @param attributionTag The attribution tag the op is noted for
+ * @param syncOp the op and attribution tag to note for
*/
- private void collectNotedOpSync(int op, @Nullable String attributionTag) {
+ private void collectNotedOpSync(@NonNull SyncNotedAppOp syncOp) {
// If this is inside of a two-way binder call:
// We are inside of a two-way binder call. Delivered to caller via
// {@link #prefixParcelWithAppOpsIfNeeded}
+ int op = sOpStrToOp.get(syncOp.getOp());
ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
if (appOpsNoted == null) {
appOpsNoted = new ArrayMap<>(1);
sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
}
- long[] appOpsNotedForAttribution = appOpsNoted.get(attributionTag);
+ long[] appOpsNotedForAttribution = appOpsNoted.get(syncOp.getAttributionTag());
if (appOpsNotedForAttribution == null) {
appOpsNotedForAttribution = new long[2];
- appOpsNoted.put(attributionTag, appOpsNotedForAttribution);
+ appOpsNoted.put(syncOp.getAttributionTag(), appOpsNotedForAttribution);
}
if (op < 64) {
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index a3d0cf2e972f..6af4d9364ad2 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -76,11 +76,11 @@ public abstract class AppOpsManagerInternal {
* @param superImpl The super implementation.
* @return The app op note result.
*/
- int noteOperation(int code, int uid, @Nullable String packageName,
+ SyncNotedAppOp noteOperation(int code, int uid, @Nullable String packageName,
@Nullable String featureId, boolean shouldCollectAsyncNotedOp,
@Nullable String message, boolean shouldCollectMessage,
@NonNull HeptFunction<Integer, Integer, String, String, Boolean, String, Boolean,
- Integer> superImpl);
+ SyncNotedAppOp> superImpl);
/**
* Allows overriding note proxy operation behavior.
@@ -94,11 +94,11 @@ public abstract class AppOpsManagerInternal {
* @param superImpl The super implementation.
* @return The app op note result.
*/
- int noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ SyncNotedAppOp noteProxyOperation(int code, @NonNull AttributionSource attributionSource,
boolean shouldCollectAsyncNotedOp, @Nullable String message,
boolean shouldCollectMessage, boolean skipProxyOperation,
@NonNull HexFunction<Integer, AttributionSource, Boolean, String, Boolean,
- Boolean, Integer> superImpl);
+ Boolean, SyncNotedAppOp> superImpl);
/**
* Allows overriding start proxy operation behavior.
@@ -113,12 +113,12 @@ public abstract class AppOpsManagerInternal {
* @param superImpl The super implementation.
* @return The app op note result.
*/
- int startProxyOperation(IBinder token, int code,
+ SyncNotedAppOp startProxyOperation(IBinder token, int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer,
AttributionSource, Boolean, Boolean, String, Boolean, Boolean,
- Integer> superImpl);
+ SyncNotedAppOp> superImpl);
/**
* Allows overriding finish proxy op.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index eb31b5294a26..89312f4b3837 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -115,6 +115,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.Executor;
class ReceiverRestrictedContext extends ContextWrapper {
@@ -3074,14 +3075,16 @@ class ContextImpl extends Context {
mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
mParams = Objects.requireNonNull(params);
- mAttributionSource = createAttributionSource(attributionTag, nextAttributionSource);
+ mAttributionSource = createAttributionSource(attributionTag, nextAttributionSource,
+ params.getRenouncedPermissions());
mContentResolver = new ApplicationContentResolver(this, mainThread);
}
private @NonNull AttributionSource createAttributionSource(@Nullable String attributionTag,
- @Nullable AttributionSource nextAttributionSource) {
- AttributionSource attributionSource = new AttributionSource(Process.myUid(), mOpPackageName,
- attributionTag, nextAttributionSource);
+ @Nullable AttributionSource nextAttributionSource,
+ @Nullable Set<String> renouncedPermissions) {
+ AttributionSource attributionSource = new AttributionSource(Process.myUid(),
+ mOpPackageName, attributionTag, renouncedPermissions, nextAttributionSource);
// If we want to access protected data on behalf of another app we need to
// tell the OS that we opt in to participate in the attribution chain.
if (nextAttributionSource != null) {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 81e5e1d96294..1b8eb8add791 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -571,6 +571,12 @@ interface IActivityManager {
*/
void stopDelegateShellPermissionIdentity();
+ /**
+ * Method for the shell UID to get currently adopted permissions for an active instrumentation.
+ * An active instrumentation is one running and started from the shell.
+ */
+ List<String> getDelegatedShellPermissions();
+
/** Returns a file descriptor that'll be closed when the system server process dies. */
ParcelFileDescriptor getLifeMonitor();
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index a5f8f103e437..dab5aff5c9a8 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -85,6 +85,7 @@ interface INotificationManager
void setBubblesAllowed(String pkg, int uid, int bubblePreference);
boolean areBubblesAllowed(String pkg);
+ boolean areBubblesEnabled(in UserHandle user);
int getBubblePreferenceForPackage(String pkg, int uid);
void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList);
@@ -227,6 +228,7 @@ interface INotificationManager
NotificationListenerFilter getListenerFilter(in ComponentName cn, int userId);
void setListenerFilter(in ComponentName cn, int userId, in NotificationListenerFilter nlf);
+ void migrateNotificationFilter(in INotificationListener token, int defaultTypes, in List<String> disallowedPkgs);
void setToastRateLimitingEnabled(boolean enable);
}
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index ec7d7832dc82..c30bc248344c 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -24,6 +24,8 @@ import android.view.WindowContentFrameStats;
import android.view.WindowAnimationFrameStats;
import android.os.ParcelFileDescriptor;
+import java.util.List;
+
/**
* This interface contains privileged operations a shell program can perform
* on behalf of an instrumentation that it runs. These operations require
@@ -54,4 +56,5 @@ interface IUiAutomationConnection {
oneway void shutdown();
void executeShellCommandWithStderr(String command, in ParcelFileDescriptor sink,
in ParcelFileDescriptor source, in ParcelFileDescriptor stderrSink);
+ List<String> getAdoptedShellPermissions();
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2fbea28f34d5..3de78f6e3cab 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3744,10 +3744,8 @@ public class Notification implements Parcelable
private int mTextColorsAreForBackground = COLOR_INVALID;
private int mPrimaryTextColor = COLOR_INVALID;
private int mSecondaryTextColor = COLOR_INVALID;
- private boolean mRebuildStyledRemoteViews;
private boolean mTintActionButtons;
- private boolean mTintWithThemeAccent;
private boolean mInNightMode;
/**
@@ -3783,7 +3781,6 @@ public class Notification implements Parcelable
mContext = context;
Resources res = mContext.getResources();
mTintActionButtons = res.getBoolean(R.bool.config_tintNotificationActionButtons);
- mTintWithThemeAccent = res.getBoolean(R.bool.config_tintNotificationsWithTheme);
if (res.getBoolean(R.bool.config_enableNightMode)) {
Configuration currentConfig = res.getConfiguration();
@@ -5208,15 +5205,21 @@ public class Notification implements Parcelable
|| mSecondaryTextColor == COLOR_INVALID
|| mTextColorsAreForBackground != backgroundColor) {
mTextColorsAreForBackground = backgroundColor;
- mPrimaryTextColor = ContrastColorUtil.resolvePrimaryColor(mContext,
+ int defaultPrimaryTextColor = ContrastColorUtil.resolvePrimaryColor(mContext,
backgroundColor, mInNightMode);
- mSecondaryTextColor = ContrastColorUtil.resolveSecondaryColor(mContext,
+ int defaultSecondaryTextColor = ContrastColorUtil.resolveSecondaryColor(mContext,
backgroundColor, mInNightMode);
- if (backgroundColor != COLOR_DEFAULT && isColorized(p)) {
+ boolean colorized = backgroundColor != COLOR_DEFAULT;
+ if (colorized) {
mPrimaryTextColor = ContrastColorUtil.findAlphaToMeetContrast(
- mPrimaryTextColor, backgroundColor, 4.5);
+ defaultPrimaryTextColor, backgroundColor, 4.5);
mSecondaryTextColor = ContrastColorUtil.findAlphaToMeetContrast(
- mSecondaryTextColor, backgroundColor, 4.5);
+ defaultSecondaryTextColor, backgroundColor, 4.5);
+ } else {
+ mPrimaryTextColor = obtainThemeColor(R.attr.textColorPrimary,
+ defaultPrimaryTextColor);
+ mSecondaryTextColor = obtainThemeColor(R.attr.textColorSecondary,
+ defaultSecondaryTextColor);
}
}
}
@@ -5243,11 +5246,9 @@ public class Notification implements Parcelable
contentView.setProgressBar(R.id.progress, max, progress, ind);
contentView.setProgressBackgroundTintList(R.id.progress,
mContext.getColorStateList(R.color.notification_progress_background_color));
- if (mTintWithThemeAccent || getRawColor(p) != COLOR_DEFAULT) {
- ColorStateList progressTint = ColorStateList.valueOf(getAccentColor(p));
- contentView.setProgressTintList(R.id.progress, progressTint);
- contentView.setProgressIndeterminateTintList(R.id.progress, progressTint);
- }
+ ColorStateList progressTint = ColorStateList.valueOf(getAccentColor(p));
+ contentView.setProgressTintList(R.id.progress, progressTint);
+ contentView.setProgressIndeterminateTintList(R.id.progress, progressTint);
return true;
} else {
contentView.setViewVisibility(R.id.progress, View.GONE);
@@ -5357,8 +5358,8 @@ public class Notification implements Parcelable
int pillColor = getProtectionColor(p);
contentView.setInt(R.id.expand_button, "setDefaultTextColor", textColor);
contentView.setInt(R.id.expand_button, "setDefaultPillColor", pillColor);
- // Use different highlighted colors except when low-priority mode prevents that
- if (!p.mReduceHighlights) {
+ // Use different highlighted colors for conversations' unread count
+ if (p.mHighlightExpander) {
pillColor = getAccentTertiaryColor(p);
// TODO(b/183710694): The accent tertiary is currently too bright in dark mode, so
// we need to pick a contrasting color.
@@ -5810,8 +5811,7 @@ public class Notification implements Parcelable
}
private boolean useExistingRemoteView() {
- return mStyle == null || (!mStyle.displayCustomViewInline()
- && !mRebuildStyledRemoteViews);
+ return mStyle == null || !mStyle.displayCustomViewInline();
}
/**
@@ -5993,7 +5993,7 @@ public class Notification implements Parcelable
.viewType(StandardTemplateParams.VIEW_TYPE_PUBLIC)
.fillTextsFrom(this);
if (isLowPriority) {
- params.reduceHighlights();
+ params.highlightExpander(false);
}
view = makeNotificationHeader(params);
view.setBoolean(R.id.notification_header, "setExpandOnlyOnButton", true);
@@ -6016,7 +6016,7 @@ public class Notification implements Parcelable
public RemoteViews makeLowPriorityContentView(boolean useRegularSubtext) {
StandardTemplateParams p = mParams.reset()
.viewType(StandardTemplateParams.VIEW_TYPE_MINIMIZED)
- .reduceHighlights()
+ .highlightExpander(false)
.fillTextsFrom(this);
if (!useRegularSubtext || TextUtils.isEmpty(mParams.summaryText)) {
p.summaryText(createSummaryText());
@@ -6083,8 +6083,7 @@ public class Notification implements Parcelable
background = outResultColor[0].getDefaultColor();
textColor = ContrastColorUtil.resolvePrimaryColor(mContext,
background, mInNightMode);
- } else if (mTintActionButtons && !mInNightMode
- && getRawColor(p) != COLOR_DEFAULT && !isColorized(p)) {
+ } else if (mTintActionButtons && !mInNightMode && !isColorized(p)) {
textColor = getAccentColor(p);
} else {
textColor = getPrimaryTextColor(p);
@@ -6262,7 +6261,7 @@ public class Notification implements Parcelable
* is the primary text color, otherwise it's the contrast-adjusted app-provided color.
*/
private @ColorInt int getSmallIconColor(StandardTemplateParams p) {
- return isColorized(p) ? getPrimaryTextColor(p) : getContrastColor(p);
+ return getContrastColor(p);
}
/**
@@ -6274,11 +6273,9 @@ public class Notification implements Parcelable
if (isColorized(p)) {
return getPrimaryTextColor(p);
}
- if (mTintWithThemeAccent) {
- int color = obtainThemeColor(R.attr.colorAccent, COLOR_INVALID);
- if (color != COLOR_INVALID) {
- return color;
- }
+ int color = obtainThemeColor(R.attr.colorAccent, COLOR_INVALID);
+ if (color != COLOR_INVALID) {
+ return color;
}
return getContrastColor(p);
}
@@ -6288,7 +6285,7 @@ public class Notification implements Parcelable
* color when colorized, or when not using theme color tints.
*/
private @ColorInt int getProtectionColor(StandardTemplateParams p) {
- if (mTintWithThemeAccent && !isColorized(p)) {
+ if (!isColorized(p)) {
int color = obtainThemeColor(R.attr.colorBackgroundFloating, COLOR_INVALID);
if (color != COLOR_INVALID) {
return color;
@@ -6307,12 +6304,10 @@ public class Notification implements Parcelable
if (isColorized(p)) {
return getPrimaryTextColor(p);
}
- if (mTintWithThemeAccent) {
- int color = obtainThemeColor(com.android.internal.R.attr.colorAccentTertiary,
- COLOR_INVALID);
- if (color != COLOR_INVALID) {
- return color;
- }
+ int color = obtainThemeColor(com.android.internal.R.attr.colorAccentTertiary,
+ COLOR_INVALID);
+ if (color != COLOR_INVALID) {
+ return color;
}
return getContrastColor(p);
}
@@ -6342,6 +6337,9 @@ public class Notification implements Parcelable
* Gets the contrast-adjusted version of the color provided by the app.
*/
private @ColorInt int getContrastColor(StandardTemplateParams p) {
+ if (isColorized(p)) {
+ return getPrimaryTextColor(p);
+ }
int rawColor = getRawColor(p);
if (mCachedContrastColorIsFor == rawColor && mCachedContrastColor != COLOR_INVALID) {
return mCachedContrastColor;
@@ -6352,9 +6350,10 @@ public class Notification implements Parcelable
int background = getDefaultBackgroundColor();
if (rawColor == COLOR_DEFAULT) {
ensureColors(p);
- color = ContrastColorUtil.resolveDefaultColor(mContext, background, mInNightMode);
- if (mTintWithThemeAccent) {
- color = obtainThemeColor(R.attr.colorAccent, color);
+ color = obtainThemeColor(R.attr.colorAccent, COLOR_INVALID);
+ if (color == COLOR_INVALID) {
+ color = ContrastColorUtil.resolveDefaultColor(mContext, background,
+ mInNightMode);
}
} else {
color = ContrastColorUtil.resolveContrastColor(mContext, rawColor,
@@ -6375,11 +6374,6 @@ public class Notification implements Parcelable
* @param p the template params to inflate this with
*/
private @ColorInt int getRawColor(StandardTemplateParams p) {
- // When notifications are theme-tinted, the raw color is only used for the icon, so go
- // ahead and keep that color instead of changing the color for minimized notifs.
- if (p.mReduceHighlights && !mTintWithThemeAccent) {
- return COLOR_DEFAULT;
- }
return mN.color;
}
@@ -6486,6 +6480,7 @@ public class Notification implements Parcelable
+ " notification: " + mN.mShortcutId
+ " vs bubble: " + mN.mBubbleMetadata.getShortcutId());
}
+ validateColorizedHasColor();
// first, add any extras from the calling code
if (mUserExtras != null) {
@@ -6539,6 +6534,21 @@ public class Notification implements Parcelable
return mN;
}
+ // This code is executed on behalf of other apps' notifications, sometimes even by 3p apps,
+ // a use case that is not supported by the Compat Framework library.
+ @SuppressWarnings("AndroidFrameworkCompatChange")
+ private void validateColorizedHasColor() {
+ if (mN.color == COLOR_DEFAULT && mN.extras.getBoolean(EXTRA_COLORIZED)) {
+ if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.S) {
+ throw new IllegalArgumentException(
+ "Colorized notifications must set a color (other than COLOR_DEFAULT).");
+ } else {
+ Log.w(TAG, "Colorized notifications must set a color (other than "
+ + "COLOR_DEFAULT). This is required for apps targeting S.");
+ }
+ }
+ }
+
/**
* Returns the color for the given Theme.DeviceDefault.DayNight attribute, or
* defValue if that could not be completed
@@ -6551,13 +6561,9 @@ public class Notification implements Parcelable
}
theme = new ContextThemeWrapper(mContext, R.style.Theme_DeviceDefault_DayNight)
.getTheme();
- TypedArray ta = theme.obtainStyledAttributes(new int[]{attrRes});
- if (ta == null) {
- return defaultColor;
+ try (TypedArray ta = theme.obtainStyledAttributes(new int[]{attrRes})) {
+ return ta == null ? defaultColor : ta.getColor(0, defaultColor);
}
- int background = ta.getColor(0, defaultColor);
- ta.recycle();
- return background;
}
/**
@@ -6671,11 +6677,7 @@ public class Notification implements Parcelable
* which must be resolved by the caller before being used.
*/
private @ColorInt int getUnresolvedBackgroundColor(StandardTemplateParams p) {
- if (isColorized(p)) {
- return getRawColor(p);
- } else {
- return COLOR_DEFAULT;
- }
+ return isColorized(p) ? getRawColor(p) : COLOR_DEFAULT;
}
/**
@@ -6700,18 +6702,6 @@ public class Notification implements Parcelable
}
/**
- * Forces all styled remoteViews to be built from scratch and not use any cached
- * RemoteViews.
- * This is needed for legacy apps that are baking in their remoteviews into the
- * notification.
- *
- * @hide
- */
- public void setRebuildStyledRemoteViews(boolean rebuild) {
- mRebuildStyledRemoteViews = rebuild;
- }
-
- /**
* Get the text that should be displayed in the statusBar when heads upped. This is
* usually just the app name, but may be different depending on the style.
*
@@ -6878,7 +6868,7 @@ public class Notification implements Parcelable
* @hide
*/
public boolean isColorized() {
- return extras.getBoolean(EXTRA_COLORIZED)
+ return color != COLOR_DEFAULT && extras.getBoolean(EXTRA_COLORIZED)
&& (hasColorizedPermission() || isForegroundService());
}
@@ -8303,6 +8293,7 @@ public class Notification implements Parcelable
StandardTemplateParams p = mBuilder.mParams.reset()
.viewType(isCollapsed ? StandardTemplateParams.VIEW_TYPE_NORMAL
: StandardTemplateParams.VIEW_TYPE_BIG)
+ .highlightExpander(isConversationLayout)
.hideProgress(true)
.title(conversationTitle)
.text(null)
@@ -8389,27 +8380,6 @@ public class Notification implements Parcelable
return true;
}
- private CharSequence createConversationTitleFromMessages() {
- ArraySet<CharSequence> names = new ArraySet<>();
- for (int i = 0; i < mMessages.size(); i++) {
- Message m = mMessages.get(i);
- Person sender = m.getSenderPerson();
- if (sender != null) {
- names.add(sender.getName());
- }
- }
- SpannableStringBuilder title = new SpannableStringBuilder();
- int size = names.size();
- for (int i = 0; i < size; i++) {
- CharSequence name = names.valueAt(i);
- if (!TextUtils.isEmpty(title)) {
- title.append(", ");
- }
- title.append(BidiFormatter.getInstance().unicodeWrap(name));
- }
- return title;
- }
-
/**
* @hide
*/
@@ -8423,11 +8393,6 @@ public class Notification implements Parcelable
return remoteViews;
}
- private static TextAppearanceSpan makeFontColorSpan(int color) {
- return new TextAppearanceSpan(null, 0, 0,
- ColorStateList.valueOf(color), null);
- }
-
public static final class Message {
/** @hide */
public static final String KEY_TEXT = "text";
@@ -9096,10 +9061,8 @@ public class Notification implements Parcelable
container.setDrawableTint(buttonId, false, tintColor,
PorterDuff.Mode.SRC_ATOP);
- final TypedArray typedArray = mBuilder.mContext.obtainStyledAttributes(
- new int[]{ android.R.attr.colorControlHighlight });
- int rippleAlpha = Color.alpha(typedArray.getColor(0, 0));
- typedArray.recycle();
+ int rippleAlpha = Color.alpha(mBuilder.obtainThemeColor(
+ android.R.attr.colorControlHighlight, COLOR_DEFAULT));
int rippleColor = Color.argb(rippleAlpha, Color.red(tintColor), Color.green(tintColor),
Color.blue(tintColor));
container.setRippleDrawableColor(buttonId, ColorStateList.valueOf(rippleColor));
@@ -9186,9 +9149,12 @@ public class Notification implements Parcelable
* </pre>
*/
public static class CallStyle extends Style {
- private static final int CALL_TYPE_INCOMING = 1;
- private static final int CALL_TYPE_ONGOING = 2;
- private static final int CALL_TYPE_SCREENING = 3;
+ /** @hide */
+ public static final int CALL_TYPE_INCOMING = 1;
+ /** @hide */
+ public static final int CALL_TYPE_ONGOING = 2;
+ /** @hide */
+ public static final int CALL_TYPE_SCREENING = 3;
/**
* This is a key used privately on the action.extras to give spacing priority
@@ -9889,23 +9855,6 @@ public class Notification implements Parcelable
// Comparison done for all custom RemoteViews, independent of style
return false;
}
-
- private RemoteViews buildIntoRemoteView(RemoteViews template, RemoteViews customContent,
- boolean headerless) {
- if (customContent != null) {
- // Need to clone customContent before adding, because otherwise it can no longer be
- // parceled independently of remoteViews.
- customContent = customContent.clone();
- customContent.overrideTextColors(mBuilder.getPrimaryTextColor(mBuilder.mParams));
- if (headerless) {
- template.removeFromParent(R.id.notification_top_line);
- }
- template.removeAllViews(R.id.notification_main_column);
- template.addView(R.id.notification_main_column, customContent);
- template.addFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED);
- }
- return template;
- }
}
/**
@@ -12230,7 +12179,7 @@ public class Notification implements Parcelable
int maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
boolean hideLargeIcon;
boolean allowColorization = true;
- boolean mReduceHighlights = false;
+ boolean mHighlightExpander = false;
final StandardTemplateParams reset() {
mViewType = VIEW_TYPE_UNSPECIFIED;
@@ -12254,7 +12203,7 @@ public class Notification implements Parcelable
maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
hideLargeIcon = false;
allowColorization = true;
- mReduceHighlights = false;
+ mHighlightExpander = false;
return this;
}
@@ -12362,8 +12311,8 @@ public class Notification implements Parcelable
return this;
}
- final StandardTemplateParams reduceHighlights() {
- this.mReduceHighlights = true;
+ final StandardTemplateParams highlightExpander(boolean highlight) {
+ this.mHighlightExpander = highlight;
return this;
}
diff --git a/core/java/android/app/NotificationHistory.java b/core/java/android/app/NotificationHistory.java
index 0c8188b9a51e..eb9ec869af12 100644
--- a/core/java/android/app/NotificationHistory.java
+++ b/core/java/android/app/NotificationHistory.java
@@ -404,6 +404,26 @@ public final class NotificationHistory implements Parcelable {
}
/**
+ * Removes all notifications from a channel and regenerates the string pool
+ */
+ public boolean removeChannelFromWrite(String packageName, String channelId) {
+ boolean removed = false;
+ for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) {
+ HistoricalNotification hn = mNotificationsToWrite.get(i);
+ if (packageName.equals(hn.getPackage())
+ && Objects.equals(channelId, hn.getChannelId())) {
+ removed = true;
+ mNotificationsToWrite.remove(i);
+ }
+ }
+ if (removed) {
+ poolStringsFromNotifications();
+ }
+
+ return removed;
+ }
+
+ /**
* Gets pooled strings in order to write them to disk
*/
public @NonNull String[] getPooledStringsToWrite() {
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 6cce270bc5a3..f0d580f066d8 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1326,7 +1326,6 @@ public class NotificationManager {
}
}
-
/**
* Gets whether all notifications posted by this app can appear outside of the
* notification shade, floating over other apps' content.
@@ -1348,6 +1347,21 @@ public class NotificationManager {
}
/**
+ * Returns whether bubbles are enabled at the feature level for the current user. When enabled,
+ * notifications able to bubble will display an affordance allowing the user to bubble them.
+ *
+ * @see Notification.Builder#setBubbleMetadata(Notification.BubbleMetadata)
+ */
+ public boolean areBubblesEnabled() {
+ INotificationManager service = getService();
+ try {
+ return service.areBubblesEnabled(mContext.getUser());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets the bubble preference for the app. This preference only applies to notifications that
* have been properly configured to bubble.
*
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index f4b95420154b..4cf3a8059b3e 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -379,8 +379,7 @@ public final class PendingIntent implements Parcelable {
if (Compatibility.isChangeEnabled(PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED)
&& !flagImmutableSet && !flagMutableSet) {
- //TODO(b/178065720) Remove check for chrome and enforce this requirement
- if (packageName.equals("com.android.chrome") || mInstrumentation.isInstrumenting()) {
+ if (mInstrumentation.isInstrumenting()) {
Log.e(TAG, msg);
} else {
throw new IllegalArgumentException(msg);
diff --git a/core/java/android/app/SyncNotedAppOp.java b/core/java/android/app/SyncNotedAppOp.java
index 0a880dc0cbb7..bc4e5436996d 100644
--- a/core/java/android/app/SyncNotedAppOp.java
+++ b/core/java/android/app/SyncNotedAppOp.java
@@ -34,19 +34,37 @@ import com.android.internal.util.DataClass;
* itself}.
*/
@Immutable
-/*@DataClass(
+@DataClass(
genEqualsHashCode = true,
+ genAidl = true,
genConstructor = false
)
-@DataClass.Suppress("getOpCode")*/
+@DataClass.Suppress({"getOpCode", "getOpMode"})
public final class SyncNotedAppOp implements Parcelable {
+ /** mode returned by the system on a call to note/startOp, if applicable */
+ private final int mOpMode;
/** op code of synchronous appop noted */
private final @IntRange(from = 0L, to = AppOpsManager._NUM_OP - 1) int mOpCode;
/** attributionTag of synchronous appop noted */
private final @Nullable String mAttributionTag;
/**
+ * Native code relies on parcel ordering, do not change
+ * @hide
+ */
+ public SyncNotedAppOp(int opMode, @IntRange(from = 0L) int opCode,
+ @Nullable String attributionTag) {
+ this.mOpCode = opCode;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mOpCode,
+ "from", 0,
+ "to", AppOpsManager._NUM_OP - 1);
+ this.mAttributionTag = attributionTag;
+ this.mOpMode = opMode;
+ }
+
+ /**
* Creates a new SyncNotedAppOp.
*
* @param opCode
@@ -55,12 +73,7 @@ public final class SyncNotedAppOp implements Parcelable {
* attributionTag of synchronous appop noted
*/
public SyncNotedAppOp(@IntRange(from = 0L) int opCode, @Nullable String attributionTag) {
- this.mOpCode = opCode;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mOpCode,
- "from", 0,
- "to", AppOpsManager._NUM_OP - 1);
- this.mAttributionTag = attributionTag;
+ this(AppOpsManager.MODE_IGNORED, opCode, attributionTag);
}
/**
@@ -70,7 +83,16 @@ public final class SyncNotedAppOp implements Parcelable {
return AppOpsManager.opToPublicName(mOpCode);
}
- // Code below generated by codegen v1.0.14.
+ /**
+ * @hide
+ */
+ public int getOpMode() {
+ return mOpMode;
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -104,6 +126,7 @@ public final class SyncNotedAppOp implements Parcelable {
SyncNotedAppOp that = (SyncNotedAppOp) o;
//noinspection PointlessBooleanExpression
return true
+ && mOpMode == that.mOpMode
&& mOpCode == that.mOpCode
&& java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
}
@@ -115,6 +138,7 @@ public final class SyncNotedAppOp implements Parcelable {
// int fieldNameHashCode() { ... }
int _hash = 1;
+ _hash = 31 * _hash + mOpMode;
_hash = 31 * _hash + mOpCode;
_hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
return _hash;
@@ -127,8 +151,9 @@ public final class SyncNotedAppOp implements Parcelable {
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (mAttributionTag != null) flg |= 0x2;
+ if (mAttributionTag != null) flg |= 0x4;
dest.writeByte(flg);
+ dest.writeInt(mOpMode);
dest.writeInt(mOpCode);
if (mAttributionTag != null) dest.writeString(mAttributionTag);
}
@@ -145,13 +170,15 @@ public final class SyncNotedAppOp implements Parcelable {
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
+ int opMode = in.readInt();
int opCode = in.readInt();
- String attributionTag = (flg & 0x2) == 0 ? null : in.readString();
+ String attributionTag = (flg & 0x4) == 0 ? null : in.readString();
+ this.mOpMode = opMode;
this.mOpCode = opCode;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mOpCode,
- "from", 0,
+ "from", 0L,
"to", AppOpsManager._NUM_OP - 1);
this.mAttributionTag = attributionTag;
@@ -172,11 +199,11 @@ public final class SyncNotedAppOp implements Parcelable {
}
};
- /*@DataClass.Generated(
- time = 1579188889960L,
- codegenVersion = "1.0.14",
+ @DataClass.Generated(
+ time = 1617317997768L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/app/SyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=AppOpsManager._NUM_OP - 1) int mOpCode\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\npublic @android.annotation.NonNull java.lang.String getOp()\npublic @android.annotation.SystemApi int getOpCode()\nclass SyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genConstructor=false)")*/
+ inputSignatures = "private final int mOpMode\nprivate final @android.annotation.IntRange int mOpCode\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\npublic @android.annotation.NonNull java.lang.String getOp()\npublic int getOpMode()\nclass SyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genConstructor=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 31b0d413c395..47a9fbb5fe4a 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -722,7 +722,7 @@ public final class SystemServiceRegistry {
new CachedServiceFetcher<UwbManager>() {
@Override
public UwbManager createService(ContextImpl ctx) {
- return UwbManager.getInstance();
+ return UwbManager.getInstance(ctx);
}
});
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 05872bad30f0..7d3db5e2cc49 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -43,6 +43,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -66,7 +67,9 @@ import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.TimeoutException;
/**
@@ -160,6 +163,16 @@ public final class UiAutomation {
*/
public static final int FLAG_DONT_USE_ACCESSIBILITY = 0x00000002;
+ /**
+ * Returned by {@link #getAdoptedShellPermissions} to indicate that all permissions have been
+ * adopted using {@link #adoptShellPermissionIdentity}.
+ *
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ public static final Set<String> ALL_PERMISSIONS = Set.of("_ALL_PERMISSIONS_");
+
private final Object mLock = new Object();
private final ArrayList<AccessibilityEvent> mEventQueue = new ArrayList<AccessibilityEvent>();
@@ -499,6 +512,25 @@ public final class UiAutomation {
}
/**
+ * Returns a list of adopted shell permissions using {@link #adoptShellPermissionIdentity},
+ * returns and empty set if no permissions are adopted and {@link #ALL_PERMISSIONS} if all
+ * permissions are adopted.
+ *
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ public Set<String> getAdoptedShellPermissions() {
+ try {
+ final List<String> permissions = mUiAutomationConnection.getAdoptedShellPermissions();
+ return permissions == null ? ALL_PERMISSIONS : new ArraySet<>(permissions);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error getting adopted shell permissions", re);
+ return Collections.emptySet();
+ }
+ }
+
+ /**
* Performs a global action. Such an action can be performed at any moment
* regardless of the current application or user location in that application.
* For example going back, going home, opening recents, etc.
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 7036b6e7dbc9..90210a9a2756 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -49,6 +49,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.List;
/**
* This is a remote object that is passed from the shell to an instrumentation
@@ -340,6 +341,22 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
}
+ @Override
+ @Nullable
+ public List<String> getAdoptedShellPermissions() throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mActivityManager.getDelegatedShellPermissions();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
public class Repeater implements Runnable {
// Continuously read readFrom and write back to writeTo until EOF is encountered
private final InputStream readFrom;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 89d08ccefb79..843aa2ecb492 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -306,10 +306,12 @@ public class DevicePolicyManager {
* succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
* that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
*
- * @deprecated admin apps must now implement activities with intent filters for the {@link
- * #ACTION_GET_PROVISIONING_MODE} and {@link #ACTION_ADMIN_POLICY_COMPLIANCE} intent actions;
- * using {@link #ACTION_PROVISION_MANAGED_DEVICE} to start provisioning will cause the
- * provisioning to fail.
+ * @deprecated to support {@link android.os.Build.VERSION_CODES#S} and later, admin apps must
+ * implement activities with intent filters for the {@link #ACTION_GET_PROVISIONING_MODE} and
+ * {@link #ACTION_ADMIN_POLICY_COMPLIANCE} intent actions; using {@link
+ * #ACTION_PROVISION_MANAGED_DEVICE} to start provisioning will cause the provisioning to fail;
+ * to additionally support pre-{@link android.os.Build.VERSION_CODES#S}, admin apps must also
+ * continue to use this constant.
*/
@Deprecated
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -1275,6 +1277,13 @@ public class DevicePolicyManager {
/**
* A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
* trigger is persistent device owner enrollment.
+ * <p>This constant is meant to represent a specific type of managed account provisioning which
+ * provisions a device to a device owner by invoking the standard provisioning flow (where
+ * the ManagedProvisioning component downloads and installs the admin app), as opposed to
+ * relying on the provisioning trigger to handle download and install of the admin app.
+ * <p>As of {@link android.os.Build.VERSION_CODES#S}, this constant is no longer used in favor
+ * of the more general {@link #PROVISIONING_TRIGGER_MANAGED_ACCOUNT} which handles all managed
+ * account provisioning types.
* @deprecated Use the broader {@link #PROVISIONING_TRIGGER_MANAGED_ACCOUNT} instead
* @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
* @see #PROVISIONING_TRIGGER_QR_CODE
@@ -1288,6 +1297,7 @@ public class DevicePolicyManager {
/**
* A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
* trigger is managed account enrollment.
+ * <p>
* @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
* @see #PROVISIONING_TRIGGER_QR_CODE
* @see #PROVISIONING_TRIGGER_UNSPECIFIED
@@ -1764,19 +1774,6 @@ public class DevicePolicyManager {
= "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED";
/**
- * Broadcast action to notify ManagedProvisioning that
- * {@link UserManager#DISALLOW_SHARE_INTO_MANAGED_PROFILE} restriction has changed.
- * @hide
- * @deprecated No longer needed as ManagedProvisioning no longer handles
- * {@link UserManager#DISALLOW_SHARE_INTO_MANAGED_PROFILE} restriction changing.
- */
- // TODO(b/177221010): Remove when Managed Provisioning no longer depend on it.
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @Deprecated
- public static final String ACTION_DATA_SHARING_RESTRICTION_CHANGED =
- "android.app.action.DATA_SHARING_RESTRICTION_CHANGED";
-
- /**
* Broadcast action from ManagedProvisioning to notify that the latest change to
* {@link UserManager#DISALLOW_SHARE_INTO_MANAGED_PROFILE} restriction has been successfully
* applied (cross profile intent filters updated). Only usesd for CTS tests.
@@ -2668,8 +2665,8 @@ public class DevicePolicyManager {
* A boolean extra which determines whether to skip the ownership disclaimer screen during the
* provisioning flow. The default value is {@code false}.
*
- * If the value is {@code true}, it is the responsibility of the provisioning initiator to
- * show the relevant disclaimer.
+ * If the value is {@code true}, the provisioning initiator must display a device ownership
+ * disclaimer screen similar to that provided in AOSP.
*
* <p>This extra is only respected when provided alongside the {@link
* #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} intent action.
@@ -2704,7 +2701,13 @@ public class DevicePolicyManager {
public static final int PROVISIONING_MODE_MANAGED_PROFILE = 2;
/**
- * The provisioning mode for a work profile on a personal device.
+ * The provisioning mode for a managed profile on a personal device.
+ * <p>This mode is only available when the provisioning initiator has explicitly instructed the
+ * provisioning flow to support managed profile on a personal device provisioning. In that case,
+ * {@link #PROVISIONING_MODE_MANAGED_PROFILE} corresponds to an organization-owned managed
+ * profile, whereas this constant corresponds to a personally-owned managed profile.
+ *
+ * @see #EXTRA_PROVISIONING_MODE
*/
public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_PERSONAL_DEVICE = 3;
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 2b52875f4b0b..fc4a2b49d0c2 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -717,7 +717,7 @@ public class AssistStructure implements Parcelable {
String mWebDomain;
Bundle mExtras;
LocaleList mLocaleList;
- String[] mOnReceiveContentMimeTypes;
+ String[] mReceiveContentMimeTypes;
ViewNode[] mChildren;
@@ -884,7 +884,7 @@ public class AssistStructure implements Parcelable {
mLocaleList = in.readParcelable(null);
}
if ((flags & FLAGS_HAS_MIME_TYPES) != 0) {
- mOnReceiveContentMimeTypes = in.readStringArray();
+ mReceiveContentMimeTypes = in.readStringArray();
}
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
mExtras = in.readBundle();
@@ -945,7 +945,7 @@ public class AssistStructure implements Parcelable {
if (mLocaleList != null) {
flags |= FLAGS_HAS_LOCALE_LIST;
}
- if (mOnReceiveContentMimeTypes != null) {
+ if (mReceiveContentMimeTypes != null) {
flags |= FLAGS_HAS_MIME_TYPES;
}
if (mExtras != null) {
@@ -1119,7 +1119,7 @@ public class AssistStructure implements Parcelable {
out.writeParcelable(mLocaleList, 0);
}
if ((flags & FLAGS_HAS_MIME_TYPES) != 0) {
- out.writeStringArray(mOnReceiveContentMimeTypes);
+ out.writeStringArray(mReceiveContentMimeTypes);
}
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
out.writeBundle(mExtras);
@@ -1540,12 +1540,12 @@ public class AssistStructure implements Parcelable {
/**
* Returns the MIME types accepted by {@link View#performReceiveContent} for this view. See
- * {@link View#getOnReceiveContentMimeTypes()} for details.
+ * {@link View#getReceiveContentMimeTypes()} for details.
*/
@Nullable
@SuppressLint("NullableCollection")
- public String[] getOnReceiveContentMimeTypes() {
- return mOnReceiveContentMimeTypes;
+ public String[] getReceiveContentMimeTypes() {
+ return mReceiveContentMimeTypes;
}
/**
@@ -2168,8 +2168,8 @@ public class AssistStructure implements Parcelable {
}
@Override
- public void setOnReceiveContentMimeTypes(@Nullable String[] mimeTypes) {
- mNode.mOnReceiveContentMimeTypes = mimeTypes;
+ public void setReceiveContentMimeTypes(@Nullable String[] mimeTypes) {
+ mNode.mReceiveContentMimeTypes = mimeTypes;
}
@Override
@@ -2449,7 +2449,7 @@ public class AssistStructure implements Parcelable {
if (localeList != null) {
Log.i(TAG, prefix + " LocaleList: " + localeList);
}
- String[] mimeTypes = node.getOnReceiveContentMimeTypes();
+ String[] mimeTypes = node.getReceiveContentMimeTypes();
if (mimeTypes != null) {
Log.i(TAG, prefix + " MIME types: " + Arrays.toString(mimeTypes));
}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 30ea5c476191..2a50e0de2145 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -67,4 +67,5 @@ interface IUsageStatsManager {
void reportUsageStop(in IBinder activity, String token, String callingPackage);
int getUsageSource();
void forceUsageSourceSettingRead();
+ long getLastTimeAnyComponentUsed(String packageName);
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 1db7e9da0bcb..542473a3d2a9 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1250,4 +1250,32 @@ public final class UsageStatsManager {
} catch (RemoteException re) {
}
}
+
+ /**
+ * Get the last time a package is used by any users including explicit user interaction and
+ * component usage, measured in milliseconds since the epoch and truncated to the boundary of
+ * last day before the exact time. For packages that are never used, the time will be the epoch.
+ * <p> Note that this usage stats is user-agnostic. </p>
+ * <p>
+ * Also note that component usage is only reported for component bindings (e.g. broadcast
+ * receiver, service, content provider) and only when such a binding would cause an app to leave
+ * the stopped state.
+ * See {@link UsageEvents.Event.USER_INTERACTION}, {@link UsageEvents.Event.APP_COMPONENT_USED}.
+ * </p>
+ *
+ * @param packageName The name of the package to be queried.
+ * @return last time the queried package is used since the epoch.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.PACKAGE_USAGE_STATS})
+ public long getLastTimeAnyComponentUsed(@NonNull String packageName) {
+ try {
+ return mService.getLastTimeAnyComponentUsed(packageName);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9fa4438cd153..cb0dad3b16c4 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -38,12 +38,14 @@ import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
import android.content.Context;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.ParcelUuid;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -857,8 +859,8 @@ public final class BluetoothAdapter {
}
synchronized (mLock) {
if (sBluetoothLeScanner == null) {
- sBluetoothLeScanner = new BluetoothLeScanner(mManagerService, getOpPackageName(),
- getAttributionTag());
+ sBluetoothLeScanner =
+ new BluetoothLeScanner(mManagerService, getAttributionSource());
}
}
return sBluetoothLeScanner;
@@ -1674,13 +1676,11 @@ public final class BluetoothAdapter {
return ActivityThread.currentOpPackageName();
}
- private String getAttributionTag() {
- // Workaround for legacy API for getting a BluetoothAdapter not
- // passing a context
+ private AttributionSource getAttributionSource() {
if (mContext != null) {
- return mContext.getAttributionTag();
+ return mContext.getAttributionSource();
}
- return null;
+ return new AttributionSource(Process.myUid(), ActivityThread.currentOpPackageName(), null);
}
/**
@@ -1721,7 +1721,7 @@ public final class BluetoothAdapter {
try {
mServiceLock.readLock().lock();
if (mService != null) {
- return mService.startDiscovery(getOpPackageName(), getAttributionTag());
+ return mService.startDiscovery(getAttributionSource());
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index fd04ccc1b530..280c845c63b0 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -26,6 +26,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManager;
+import android.content.AttributionSource;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
@@ -83,9 +84,7 @@ public final class BluetoothLeScanner {
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients;
-
- private final String mOpPackageName;
- private final String mFeatureId;
+ private final AttributionSource mAttributionSource;
/**
* Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
@@ -96,13 +95,12 @@ public final class BluetoothLeScanner {
* @hide
*/
public BluetoothLeScanner(IBluetoothManager bluetoothManager,
- @NonNull String opPackageName, @Nullable String featureId) {
+ @NonNull AttributionSource attributionSource) {
mBluetoothManager = bluetoothManager;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = new Handler(Looper.getMainLooper());
mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>();
- mOpPackageName = opPackageName;
- mFeatureId = featureId;
+ mAttributionSource = attributionSource;
}
/**
@@ -268,8 +266,7 @@ public final class BluetoothLeScanner {
wrapper.startRegistration();
} else {
try {
- gatt.startScanForIntent(callbackIntent, settings, filters, mOpPackageName,
- mFeatureId);
+ gatt.startScanForIntent(callbackIntent, settings, filters, mAttributionSource);
} catch (RemoteException e) {
return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
}
@@ -310,7 +307,7 @@ public final class BluetoothLeScanner {
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
- gatt.stopScanForIntent(callbackIntent, mOpPackageName);
+ gatt.stopScanForIntent(callbackIntent);
} catch (RemoteException e) {
}
}
@@ -470,7 +467,7 @@ public final class BluetoothLeScanner {
} else {
mScannerId = scannerId;
mBluetoothGatt.startScan(mScannerId, mSettings, mFilters,
- mResultStorages, mOpPackageName, mFeatureId);
+ mResultStorages, mAttributionSource);
}
} catch (RemoteException e) {
Log.e(TAG, "fail to start le scan: " + e);
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 053bfc1a3253..c851519e9b50 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -179,6 +179,15 @@ public final class AttributionSource implements Parcelable {
}
/** @hide */
+ @TestApi
+ public AttributionSource(int uid, @Nullable String packageName,
+ @Nullable String attributionTag, @Nullable Set<String> renouncedPermissions,
+ @Nullable AttributionSource next) {
+ this(uid, packageName, attributionTag, /*token*/ null,
+ renouncedPermissions, next);
+ }
+
+ /** @hide */
public AttributionSource(@NonNull AttributionSource current,
@Nullable AttributionSource next) {
this(current.getUid(), current.getPackageName(), current.getAttributionTag(),
@@ -526,7 +535,7 @@ public final class AttributionSource implements Parcelable {
/**
* The package that is accessing the permission protected data.
*/
- public @NonNull Builder setPackageName(@NonNull String value) {
+ public @NonNull Builder setPackageName(@Nullable String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
mPackageName = value;
@@ -536,7 +545,7 @@ public final class AttributionSource implements Parcelable {
/**
* The attribution tag of the app accessing the permission protected data.
*/
- public @NonNull Builder setAttributionTag(@NonNull String value) {
+ public @NonNull Builder setAttributionTag(@Nullable String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
mAttributionTag = value;
@@ -550,7 +559,7 @@ public final class AttributionSource implements Parcelable {
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
- public @NonNull Builder setRenouncedPermissions(@NonNull Set<String> value) {
+ public @NonNull Builder setRenouncedPermissions(@Nullable Set<String> value) {
checkNotUsed();
mBuilderFieldsSet |= 0x10;
mRenouncedPermissions = value;
@@ -560,7 +569,7 @@ public final class AttributionSource implements Parcelable {
/**
* The next app to receive the permission protected data.
*/
- public @NonNull Builder setNext(@NonNull AttributionSource value) {
+ public @NonNull Builder setNext(@Nullable AttributionSource value) {
checkNotUsed();
mBuilderFieldsSet |= 0x20;
mNext = value;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 232daa8f8b47..36769825c439 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4165,6 +4165,7 @@ public abstract class Context {
* @see android.net.PacProxyManager
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final String PAC_PROXY_SERVICE = "pac_proxy";
/**
diff --git a/core/java/android/content/ContextParams.java b/core/java/android/content/ContextParams.java
index bd3eaea24126..ace2ba721c10 100644
--- a/core/java/android/content/ContextParams.java
+++ b/core/java/android/content/ContextParams.java
@@ -16,10 +16,13 @@
package android.content;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.app.ActivityThread;
+import android.content.pm.PackageManager;
import java.util.Collections;
import java.util.Objects;
@@ -179,6 +182,13 @@ public final class ContextParams {
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
public @NonNull Builder setRenouncedPermissions(
@Nullable Set<String> renouncedPermissions) {
+ // This is not a security check but a fail fast - the OS enforces the permission too
+ if (renouncedPermissions != null && !renouncedPermissions.isEmpty()
+ && ActivityThread.currentApplication().checkSelfPermission(Manifest.permission
+ .RENOUNCE_PERMISSIONS) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Renouncing permissions requires: "
+ + Manifest.permission.RENOUNCE_PERMISSIONS);
+ }
mRenouncedPermissions = renouncedPermissions;
return this;
}
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index fc963fef3eb4..049bfe7f23fb 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -979,7 +979,9 @@ public final class PermissionChecker {
int uid, @NonNull Set<String> renouncedPermissions) {
final boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
uid) == PackageManager.PERMISSION_GRANTED;
- if (permissionGranted && renouncedPermissions.contains(permission)) {
+ if (permissionGranted && renouncedPermissions.contains(permission)
+ && context.checkPermission(Manifest.permission.RENOUNCE_PERMISSIONS,
+ /*pid*/ -1, uid) == PackageManager.PERMISSION_GRANTED) {
return false;
}
return permissionGranted;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0952b3e1233c..fa9142ca9449 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -896,11 +896,13 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
};
/**
- * This change id forces the packages it is applied to to be resizable. We only allow resizing
- * in fullscreen windowing mode, but not forcing the app into resizable multi-windowing mode.
+ * This change id forces the packages it is applied to be resizable. It won't change whether
+ * the app can be put into multi-windowing mode, but allow the app to resize when the window
+ * container resizes, such as display size change.
* @hide
*/
@ChangeId
+ @Overridable
@Disabled
@TestApi
public static final long FORCE_RESIZE_APP = 174042936L; // buganizer id
@@ -910,6 +912,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
* @hide
*/
@ChangeId
+ @Overridable
@Disabled
@TestApi
public static final long FORCE_NON_RESIZE_APP = 181136395L; // buganizer id
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 93acb7df7e30..3724ab942428 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2289,7 +2289,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0;
}
- /** @hide */
+ /**
+ * True if the application is pre-installed on the OEM partition of the system image.
+ * @hide
+ */
@SystemApi
public boolean isOem() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
@@ -2337,13 +2340,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
- /** @hide */
+ /**
+ * True if the application is pre-installed on the vendor partition of the system image.
+ * @hide
+ */
@SystemApi
public boolean isVendor() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
- /** @hide */
+ /**
+ * True if the application is pre-installed on the product partition of the system image.
+ * @hide
+ */
@SystemApi
public boolean isProduct() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 60aac76fa8a5..97e1b543520e 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -72,7 +72,6 @@ import com.android.internal.util.Parcelling.BuiltIn.ForInternedStringValueMap;
import com.android.internal.util.Parcelling.BuiltIn.ForStringSet;
import java.security.PublicKey;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -227,6 +226,14 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
@NonNull
@DataClass.ParcelWith(ForInternedStringList.class)
protected List<String> adoptPermissions = emptyList();
+ /**
+ * @deprecated consider migrating to {@link #getUsesPermissions} which has
+ * more parsed details, such as flags
+ */
+ @NonNull
+ @Deprecated
+ @DataClass.ParcelWith(ForInternedStringList.class)
+ protected List<String> requestedPermissions = emptyList();
@NonNull
private List<ParsedUsesPermission> usesPermissions = emptyList();
@@ -701,6 +708,11 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
@Override
public ParsingPackageImpl addUsesPermission(ParsedUsesPermission permission) {
this.usesPermissions = CollectionUtils.add(this.usesPermissions, permission);
+
+ // Continue populating legacy data structures to avoid performance
+ // issues until all that code can be migrated
+ this.requestedPermissions = CollectionUtils.add(this.requestedPermissions, permission.name);
+
return this;
}
@@ -1142,6 +1154,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
dest.writeByteArray(this.restrictUpdateHash);
dest.writeStringList(this.originalPackages);
sForInternedStringList.parcel(this.adoptPermissions, dest, flags);
+ sForInternedStringList.parcel(this.requestedPermissions, dest, flags);
dest.writeTypedList(this.usesPermissions);
sForInternedStringList.parcel(this.implicitPermissions, dest, flags);
sForStringSet.parcel(this.upgradeKeySets, dest, flags);
@@ -1264,6 +1277,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
this.restrictUpdateHash = in.createByteArray();
this.originalPackages = in.createStringArrayList();
this.adoptPermissions = sForInternedStringList.unparcel(in);
+ this.requestedPermissions = sForInternedStringList.unparcel(in);
this.usesPermissions = in.createTypedArrayList(ParsedUsesPermission.CREATOR);
this.implicitPermissions = sForInternedStringList.unparcel(in);
this.upgradeKeySets = sForStringSet.unparcel(in);
@@ -1331,7 +1345,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
this.gwpAsanMode = in.readInt();
this.minExtensionVersions = in.readSparseIntArray();
this.mBooleans = in.readLong();
- this.mProperties = in.createTypedArrayMap(Property.CREATOR);
+ this.mProperties = in.readHashMap(boot);
this.memtagMode = in.readInt();
this.nativeHeapZeroInitialized = in.readInt();
this.requestOptimizedExternalStorageAccess = sForBoolean.unparcel(in);
@@ -1558,15 +1572,14 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
return adoptPermissions;
}
+ /**
+ * @deprecated consider migrating to {@link #getUsesPermissions} which has
+ * more parsed details, such as flags
+ */
@NonNull
@Override
+ @Deprecated
public List<String> getRequestedPermissions() {
- final List<ParsedUsesPermission> usesPermissions = getUsesPermissions();
- final int size = usesPermissions.size();
- final List<String> requestedPermissions = new ArrayList<>(size);
- for (int i = 0; i < size; i++) {
- requestedPermissions.add(usesPermissions.get(i).name);
- }
return requestedPermissions;
}
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index cdd8265ad5cd..4c6255da0a39 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -376,10 +376,13 @@ public class ColorStateList extends ComplexColor implements Parcelable {
int[] stateSpec = new int[numAttrs];
for (int i = 0; i < numAttrs; i++) {
final int stateResId = attrs.getAttributeNameResource(i);
+ if (stateResId == R.attr.lStar) {
+ // Non-finalized resource ids cannot be used in switch statements.
+ continue;
+ }
switch (stateResId) {
case R.attr.color:
case R.attr.alpha:
- case R.attr.lStar:
// Recognized attribute, ignore.
break;
default:
diff --git a/core/java/android/content/res/loader/ResourcesProvider.java b/core/java/android/content/res/loader/ResourcesProvider.java
index 0a698d18682b..463dcaced723 100644
--- a/core/java/android/content/res/loader/ResourcesProvider.java
+++ b/core/java/android/content/res/loader/ResourcesProvider.java
@@ -284,11 +284,6 @@ public class ResourcesProvider implements AutoCloseable, Closeable {
Log.w(TAG, "ResourcesProvider " + this + " finalized with non-zero refs: "
+ mOpenCount);
}
-
- if (mOpen) {
- mOpen = false;
- mApkAssets.close();
- }
}
}
}
diff --git a/core/java/android/content/rollback/RollbackManagerFrameworkInitializer.java b/core/java/android/content/rollback/RollbackManagerFrameworkInitializer.java
index c5e4f9947550..24617a0bcb9a 100644
--- a/core/java/android/content/rollback/RollbackManagerFrameworkInitializer.java
+++ b/core/java/android/content/rollback/RollbackManagerFrameworkInitializer.java
@@ -15,7 +15,6 @@
*/
package android.content.rollback;
-import android.annotation.SystemApi;
import android.app.SystemServiceRegistry;
import android.content.Context;
@@ -24,7 +23,6 @@ import android.content.Context;
*
* @hide
*/
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public class RollbackManagerFrameworkInitializer {
private RollbackManagerFrameworkInitializer() {}
diff --git a/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java b/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
index 8c7695ad5a5a..fbc951e2f6e6 100644
--- a/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
+++ b/core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
@@ -16,6 +16,7 @@
package android.graphics.fonts;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
@@ -213,6 +214,16 @@ public final class FontFamilyUpdateRequest {
public List<FontVariationAxis> getAxes() {
return mAxes;
}
+
+ /**
+ * Returns the index of collection
+ *
+ * TODO(183752879): Make font index configurable and make this SystemApi.
+ * @hide
+ */
+ public @IntRange(from = 0) int getIndex() {
+ return 0;
+ }
}
/**
diff --git a/core/java/android/graphics/fonts/FontUpdateRequest.java b/core/java/android/graphics/fonts/FontUpdateRequest.java
index b79c8f62d492..4dd5a72d446e 100644
--- a/core/java/android/graphics/fonts/FontUpdateRequest.java
+++ b/core/java/android/graphics/fonts/FontUpdateRequest.java
@@ -17,19 +17,24 @@
package android.graphics.fonts;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.LocaleList;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.text.FontConfig;
+import android.util.TypedXmlSerializer;
-import java.io.File;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Represents a font update request. Currently only font install request is supported.
@@ -47,6 +52,273 @@ public final class FontUpdateRequest implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface Type {}
+ /**
+ * Font object used for update.
+ *
+ * Here is an example of Family/Font XML.
+ * <family name="my-sans">
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 400 'ital' 0" index="0" />
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 400 'ital' 1" index="0" />
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 700 'ital' 0" index="0" />
+ * <font name="MySans" weight="400" slant="0" axis="'wght' 700 'ital' 1" index="0" />
+ * </family>
+ *
+ * @see Font#readFromXml(XmlPullParser)
+ * @see Font#writeToXml(TypedXmlSerializer, Font)
+ * @see Family#readFromXml(XmlPullParser)
+ * @see Family#writeFamilyToXml(TypedXmlSerializer, Family)
+ */
+ public static final class Font implements Parcelable {
+ private static final String ATTR_INDEX = "index";
+ private static final String ATTR_WEIGHT = "weight";
+ private static final String ATTR_SLANT = "slant";
+ private static final String ATTR_AXIS = "axis";
+ private static final String ATTR_POSTSCRIPT_NAME = "name";
+
+ private final @NonNull String mPostScriptName;
+ private final @NonNull FontStyle mFontStyle;
+ private final @IntRange(from = 0) int mIndex;
+ private final @NonNull String mFontVariationSettings;
+
+ public Font(@NonNull String postScriptName, @NonNull FontStyle fontStyle,
+ @IntRange(from = 0) int index, @NonNull String fontVariationSettings) {
+ mPostScriptName = postScriptName;
+ mFontStyle = fontStyle;
+ mIndex = index;
+ mFontVariationSettings = fontVariationSettings;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString8(mPostScriptName);
+ dest.writeInt(mFontStyle.getWeight());
+ dest.writeInt(mFontStyle.getSlant());
+ dest.writeInt(mIndex);
+ dest.writeString8(mFontVariationSettings);
+ }
+
+ public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() {
+ @Override
+ public Font createFromParcel(Parcel source) {
+ String fontName = source.readString8();
+ int weight = source.readInt();
+ int slant = source.readInt();
+ int index = source.readInt();
+ String varSettings = source.readString8();
+ return new Font(fontName, new FontStyle(weight, slant), index, varSettings);
+ }
+
+ @Override
+ public Font[] newArray(int size) {
+ return new Font[size];
+ }
+ };
+
+ /**
+ * Write {@link Font} instance to XML file.
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param out output XML serializer
+ * @param font a Font instance to be written.
+ */
+ public static void writeToXml(TypedXmlSerializer out, Font font) throws IOException {
+ out.attribute(null, ATTR_POSTSCRIPT_NAME, font.getPostScriptName());
+ out.attributeInt(null, ATTR_INDEX, font.getIndex());
+ out.attributeInt(null, ATTR_WEIGHT, font.getFontStyle().getWeight());
+ out.attributeInt(null, ATTR_SLANT, font.getFontStyle().getSlant());
+ out.attribute(null, ATTR_AXIS, font.getFontVariationSettings());
+ }
+
+ /**
+ * Read {@link Font} instance from &lt;font&gt; element in XML
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param parser a parser that point &lt;font&gt; element.
+ * @return a font instance
+ * @throws IOException if font element is invalid.
+ */
+ public static Font readFromXml(XmlPullParser parser) throws IOException {
+ String psName = parser.getAttributeValue(null, ATTR_POSTSCRIPT_NAME);
+ if (psName == null) {
+ throw new IOException("name attribute is missing font tag.");
+ }
+ int index = getAttributeValueInt(parser, ATTR_INDEX, 0);
+ int weight = getAttributeValueInt(parser, ATTR_WEIGHT, FontStyle.FONT_WEIGHT_NORMAL);
+ int slant = getAttributeValueInt(parser, ATTR_SLANT, FontStyle.FONT_SLANT_UPRIGHT);
+ String varSettings = parser.getAttributeValue(null, ATTR_AXIS);
+ if (varSettings == null) {
+ varSettings = "";
+ }
+ return new Font(psName, new FontStyle(weight, slant), index, varSettings);
+ }
+
+ public @NonNull String getPostScriptName() {
+ return mPostScriptName;
+ }
+
+ public @NonNull FontStyle getFontStyle() {
+ return mFontStyle;
+ }
+
+ public @IntRange(from = 0) int getIndex() {
+ return mIndex;
+ }
+
+ public @NonNull String getFontVariationSettings() {
+ return mFontVariationSettings;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Font font = (Font) o;
+ return mIndex == font.mIndex
+ && mPostScriptName.equals(font.mPostScriptName)
+ && mFontStyle.equals(font.mFontStyle)
+ && mFontVariationSettings.equals(font.mFontVariationSettings);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPostScriptName, mFontStyle, mIndex, mFontVariationSettings);
+ }
+
+ @Override
+ public String toString() {
+ return "Font{"
+ + "mPostScriptName='" + mPostScriptName + '\''
+ + ", mFontStyle=" + mFontStyle
+ + ", mIndex=" + mIndex
+ + ", mFontVariationSettings='" + mFontVariationSettings + '\''
+ + '}';
+ }
+ }
+
+ /**
+ * Font Family object used for update request.
+ */
+ public static final class Family implements Parcelable {
+ private static final String TAG_FAMILY = "family";
+ private static final String ATTR_NAME = "name";
+ private static final String TAG_FONT = "font";
+
+ private final @Nullable String mName;
+ private final @NonNull List<Font> mFonts;
+
+ public Family(String name, List<Font> fonts) {
+ mName = name;
+ mFonts = fonts;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString8(mName);
+ dest.writeParcelableList(mFonts, flags);
+ }
+
+ public static final @NonNull Creator<Family> CREATOR = new Creator<Family>() {
+
+ @Override
+ public Family createFromParcel(Parcel source) {
+ String familyName = source.readString8();
+ List<Font> fonts = source.readParcelableList(
+ new ArrayList<>(), Font.class.getClassLoader());
+ return new Family(familyName, fonts);
+ }
+
+ @Override
+ public Family[] newArray(int size) {
+ return new Family[size];
+ }
+ };
+
+ /**
+ * Write {@link Family} instance to XML.
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param out an output XML serializer
+ * @param family a {@link Family} instance to be written
+ */
+ public static void writeFamilyToXml(@NonNull TypedXmlSerializer out, @NonNull Family family)
+ throws IOException {
+ out.attribute(null, ATTR_NAME, family.getName());
+ List<Font> fonts = family.getFonts();
+ for (int i = 0; i < fonts.size(); ++i) {
+ Font font = fonts.get(i);
+ out.startTag(null, TAG_FONT);
+ Font.writeToXml(out, font);
+ out.endTag(null, TAG_FONT);
+ }
+ }
+
+ /**
+ * Read a {@link Family} instance from &lt;family&gt; element in XML
+ *
+ * For the XML format, see {@link Font} class comment.
+ *
+ * @param parser an XML parser that points &lt;family&gt; element.
+ * @return an {@link Family} instance
+ */
+ public static @NonNull Family readFromXml(@NonNull XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ List<Font> fonts = new ArrayList<>();
+ if (parser.getEventType() != XmlPullParser.START_TAG
+ || !parser.getName().equals(TAG_FAMILY)) {
+ throw new IOException("Unexpected parser state: must be START_TAG with family");
+ }
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ int type = 0;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_FONT)) {
+ fonts.add(Font.readFromXml(parser));
+ } else if (type == XmlPullParser.END_TAG && parser.getName().equals(TAG_FAMILY)) {
+ break;
+ }
+ }
+ return new Family(name, fonts);
+ }
+
+ public @NonNull String getName() {
+ return mName;
+ }
+
+ public @NonNull List<Font> getFonts() {
+ return mFonts;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Family family = (Family) o;
+ return mName.equals(family.mName) && mFonts.equals(family.mFonts);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mName, mFonts);
+ }
+
+ @Override
+ public String toString() {
+ return "Family{mName='" + mName + '\'' + ", mFonts=" + mFonts + '}';
+ }
+ }
+
public static final Creator<FontUpdateRequest> CREATOR = new Creator<FontUpdateRequest>() {
@Override
public FontUpdateRequest createFromParcel(Parcel in) {
@@ -68,7 +340,7 @@ public final class FontUpdateRequest implements Parcelable {
private final byte[] mSignature;
// NonNull if mType == TYPE_UPDATE_FONT_FAMILY.
@Nullable
- private final FontConfig.FontFamily mFontFamily;
+ private final Family mFontFamily;
public FontUpdateRequest(@NonNull ParcelFileDescriptor fd, @NonNull byte[] signature) {
mType = TYPE_UPDATE_FONT_FILE;
@@ -77,31 +349,29 @@ public final class FontUpdateRequest implements Parcelable {
mFontFamily = null;
}
- public FontUpdateRequest(@NonNull FontConfig.FontFamily fontFamily) {
+ public FontUpdateRequest(@NonNull Family fontFamily) {
mType = TYPE_UPDATE_FONT_FAMILY;
mFd = null;
mSignature = null;
mFontFamily = fontFamily;
}
- public FontUpdateRequest(@NonNull String postScriptName,
+ public FontUpdateRequest(@NonNull String familyName,
@NonNull List<FontFamilyUpdateRequest.Font> variations) {
- // TODO: Serialize the request directly instead of reusing FontConfig.FontFamily.
- this(createFontFamily(postScriptName, variations));
+ this(createFontFamily(familyName, variations));
}
- private static FontConfig.FontFamily createFontFamily(@NonNull String postScriptName,
+ private static Family createFontFamily(@NonNull String familyName,
@NonNull List<FontFamilyUpdateRequest.Font> fonts) {
- List<FontConfig.Font> configFonts = new ArrayList<>(fonts.size());
+ List<Font> updateFonts = new ArrayList<>(fonts.size());
for (FontFamilyUpdateRequest.Font font : fonts) {
- // TODO: Support .otf.
- configFonts.add(new FontConfig.Font(new File(font.getPostScriptName() + ".ttf"), null,
- font.getStyle(), 0 /* index */,
- FontVariationAxis.toFontVariationSettings(font.getAxes()),
- null /* fontFamilyName */));
- }
- return new FontConfig.FontFamily(configFonts, postScriptName,
- LocaleList.getEmptyLocaleList(), FontConfig.FontFamily.VARIANT_DEFAULT);
+ updateFonts.add(new Font(
+ font.getPostScriptName(),
+ font.getStyle(),
+ font.getIndex(),
+ FontVariationAxis.toFontVariationSettings(font.getAxes())));
+ }
+ return new Family(familyName, updateFonts);
}
protected FontUpdateRequest(Parcel in) {
@@ -126,7 +396,7 @@ public final class FontUpdateRequest implements Parcelable {
}
@Nullable
- public FontConfig.FontFamily getFontFamily() {
+ public Family getFontFamily() {
return mFontFamily;
}
@@ -142,4 +412,17 @@ public final class FontUpdateRequest implements Parcelable {
dest.writeBlob(mSignature);
dest.writeParcelable(mFontFamily, flags);
}
+
+ // Utility functions
+ private static int getAttributeValueInt(XmlPullParser parser, String name, int defaultValue) {
+ try {
+ String value = parser.getAttributeValue(null, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
}
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index ff1a17e07c11..41672b7cbaea 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -38,7 +38,7 @@ import java.util.concurrent.TimeUnit;
*/
@TestApi
public class BiometricTestSession implements AutoCloseable {
- private static final String TAG = "BiometricTestSession";
+ private static final String BASE_TAG = "BiometricTestSession";
/**
* @hide
@@ -66,12 +66,12 @@ public class BiometricTestSession implements AutoCloseable {
private final ITestSessionCallback mCallback = new ITestSessionCallback.Stub() {
@Override
public void onCleanupStarted(int userId) {
- Log.d(TAG, "onCleanupStarted, sensor: " + mSensorId + ", userId: " + userId);
+ Log.d(getTag(), "onCleanupStarted, sensor: " + mSensorId + ", userId: " + userId);
}
@Override
public void onCleanupFinished(int userId) {
- Log.d(TAG, "onCleanupFinished, sensor: " + mSensorId
+ Log.d(getTag(), "onCleanupFinished, sensor: " + mSensorId
+ ", userId: " + userId
+ ", remaining users: " + mUsersCleaningUp.size());
mUsersCleaningUp.remove(userId);
@@ -107,7 +107,7 @@ public class BiometricTestSession implements AutoCloseable {
@RequiresPermission(TEST_BIOMETRIC)
private void setTestHalEnabled(boolean enabled) {
try {
- Log.w(TAG, "setTestHalEnabled, sensor: " + mSensorId + " enabled: " + enabled);
+ Log.w(getTag(), "setTestHalEnabled, sensor: " + mSensorId + " enabled: " + enabled);
mTestSession.setTestHalEnabled(enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -217,7 +217,7 @@ public class BiometricTestSession implements AutoCloseable {
public void cleanupInternalState(int userId) {
try {
if (mUsersCleaningUp.contains(userId)) {
- Log.w(TAG, "Cleanup already in progress for user: " + userId);
+ Log.w(getTag(), "Cleanup already in progress for user: " + userId);
}
mUsersCleaningUp.add(userId);
@@ -230,6 +230,7 @@ public class BiometricTestSession implements AutoCloseable {
@Override
@RequiresPermission(TEST_BIOMETRIC)
public void close() {
+ Log.d(getTag(), "Close, mTestedUsers size; " + mTestedUsers.size());
// Cleanup can be performed using the test HAL, since it always responds to enumerate with
// zero enrollments.
if (!mTestedUsers.isEmpty()) {
@@ -239,15 +240,19 @@ public class BiometricTestSession implements AutoCloseable {
}
try {
- Log.d(TAG, "Awaiting latch...");
- mCloseLatch.await(10, TimeUnit.SECONDS);
- Log.d(TAG, "Finished awaiting");
+ Log.d(getTag(), "Awaiting latch...");
+ mCloseLatch.await(3, TimeUnit.SECONDS);
+ Log.d(getTag(), "Finished awaiting");
} catch (InterruptedException e) {
- Log.e(TAG, "Latch interrupted", e);
+ Log.e(getTag(), "Latch interrupted", e);
}
}
// Disable the test HAL after the sensor becomes idle.
setTestHalEnabled(false);
}
+
+ private String getTag() {
+ return BASE_TAG + "_" + mSensorId;
+ }
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 8b53fc748b7b..293c0af04b8b 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1400,6 +1400,8 @@ public final class CameraManager {
// devices going offline (in real world scenarios, these permissions aren't
// changeable). Future calls to getCameraIdList() will reflect the changes in
// the camera id list after getCameraIdListNoLazy() is called.
+ // We need to remove the torch ids which may have been associated with the
+ // devices removed as well. This is the same situation.
cameraStatuses = mCameraService.addListener(testListener);
mCameraService.removeListener(testListener);
for (CameraStatus c : cameraStatuses) {
@@ -1418,6 +1420,7 @@ public final class CameraManager {
}
for (String id : deviceIdsToRemove) {
onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, id);
+ mTorchStatus.remove(id);
}
} catch (ServiceSpecificException e) {
// Unexpected failure
@@ -1518,7 +1521,11 @@ public final class CameraManager {
*/
public boolean cameraIdHasConcurrentStreamsLocked(String cameraId) {
if (!mDeviceStatus.containsKey(cameraId)) {
- Log.e(TAG, "cameraIdHasConcurrentStreamsLocked called on non existing camera id");
+ // physical camera ids aren't advertised in concurrent camera id combinations.
+ if (DEBUG) {
+ Log.v(TAG, " physical camera id " + cameraId + " is hidden." +
+ " Available logical camera ids : " + mDeviceStatus.toString());
+ }
return false;
}
for (Set<String> comb : mConcurrentCameraIdCombinations) {
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionForwardProcessor.java b/core/java/android/hardware/camera2/impl/CameraExtensionForwardProcessor.java
index 8eb1dccdf65e..bf4593260a70 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionForwardProcessor.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionForwardProcessor.java
@@ -25,6 +25,7 @@ import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
import android.annotation.NonNull;
+import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
@@ -39,6 +40,7 @@ public class CameraExtensionForwardProcessor {
private final IPreviewImageProcessorImpl mProcessor;
private final long mOutputSurfaceUsage;
private final int mOutputSurfaceFormat;
+ private final Handler mHandler;
private ImageReader mIntermediateReader = null;
private Surface mIntermediateSurface = null;
@@ -48,10 +50,11 @@ public class CameraExtensionForwardProcessor {
private boolean mOutputAbandoned = false;
public CameraExtensionForwardProcessor(@NonNull IPreviewImageProcessorImpl processor,
- int format, long surfaceUsage) {
+ int format, long surfaceUsage, @NonNull Handler handler) {
mProcessor = processor;
mOutputSurfaceUsage = surfaceUsage;
mOutputSurfaceFormat = format;
+ mHandler = handler;
}
public void close() {
@@ -98,7 +101,7 @@ public class CameraExtensionForwardProcessor {
mResolution.getHeight(), CameraExtensionCharacteristics.PROCESSING_INPUT_FORMAT,
FORWARD_QUEUE_SIZE, mOutputSurfaceUsage);
mIntermediateSurface = mIntermediateReader.getSurface();
- mIntermediateReader.setOnImageAvailableListener(new ForwardCallback(), null);
+ mIntermediateReader.setOnImageAvailableListener(new ForwardCallback(), mHandler);
mProcessor.onOutputSurface(mIntermediateSurface, mOutputSurfaceFormat);
// PreviewImageProcessorImpl always expect the extension processing format as input
@@ -124,11 +127,15 @@ public class CameraExtensionForwardProcessor {
@Override public void onImageAvailable(ImageReader reader) {
Image processedImage = null;
try {
- processedImage = mIntermediateReader.acquireNextImage();
+ processedImage = reader.acquireNextImage();
} catch (IllegalStateException e) {
Log.e(TAG, "Failed to acquire processed image!");
return;
}
+ if (processedImage == null) {
+ Log.e(TAG, "Invalid image");
+ return;
+ }
if (mOutputSurface != null && mOutputSurface.isValid() && !mOutputAbandoned) {
if (mOutputWriter == null) {
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index 1f5098f80735..3d771c01e8ac 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -352,7 +352,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
try {
mPreviewImageProcessor = new CameraExtensionForwardProcessor(
mPreviewExtender.getPreviewImageProcessor(), repeatingSurfaceInfo.mFormat,
- repeatingSurfaceInfo.mUsage);
+ repeatingSurfaceInfo.mUsage, mHandler);
} catch (ClassCastException e) {
throw new UnsupportedOperationException("Failed casting preview processor!");
}
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 29bdee3edcee..bd8df8724f92 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -63,27 +63,32 @@ public final class MandatoryStreamCombination {
private final ArrayList<Size> mAvailableSizes = new ArrayList<Size> ();
private final boolean mIsInput;
private final boolean mIsUltraHighResolution;
+ private final boolean mIsMaximumSize;
/**
* Create a new {@link MandatoryStreamInformation}.
*
- @param availableSizes List of possible stream sizes.
+ * @param availableSizes List of possible stream sizes.
* @param format Image format.
+ * @param isMaximumSize Whether this is a maximum size stream.
*
* @throws IllegalArgumentException
* if sizes is empty or if the format was not user-defined in
* ImageFormat/PixelFormat.
* @hide
*/
- public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format) {
- this(availableSizes, format, /*isInput*/false, /*maximumResolution*/false);
+ public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format,
+ boolean isMaximumSize) {
+ this(availableSizes, format, isMaximumSize, /*isInput*/false,
+ /*isUltraHighResolution*/false);
}
/**
* Create a new {@link MandatoryStreamInformation}.
*
- @param availableSizes List of possible stream sizes.
+ * @param availableSizes List of possible stream sizes.
* @param format Image format.
+ * @param isMaximumSize Whether this is a maximum size stream.
* @param isInput Flag indicating whether this stream is input.
*
* @throws IllegalArgumentException
@@ -92,17 +97,20 @@ public final class MandatoryStreamCombination {
* @hide
*/
public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format,
- boolean isInput) {
- this(availableSizes, format, isInput, /*maximumResolution*/ false);
+ boolean isMaximumSize, boolean isInput) {
+ this(availableSizes, format, isMaximumSize, isInput,
+ /*isUltraHighResolution*/ false);
}
/**
* Create a new {@link MandatoryStreamInformation}.
*
- @param availableSizes List of possible stream sizes.
+ * @param availableSizes List of possible stream sizes.
* @param format Image format.
+ * @param isMaximumSize Whether this is a maximum size stream.
* @param isInput Flag indicating whether this stream is input.
- * @param isMaxResolution Flag indicating whether this is a maximum resolution stream.
+ * @param isUltraHighResolution Flag indicating whether this is a ultra-high resolution
+ * stream.
*
* @throws IllegalArgumentException
* if sizes is empty or if the format was not user-defined in
@@ -110,12 +118,13 @@ public final class MandatoryStreamCombination {
* @hide
*/
public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format,
- boolean isInput, boolean isUltraHighResolution) {
+ boolean isMaximumSize, boolean isInput, boolean isUltraHighResolution) {
if (availableSizes.isEmpty()) {
throw new IllegalArgumentException("No available sizes");
}
mAvailableSizes.addAll(availableSizes);
mFormat = checkArgumentFormat(format);
+ mIsMaximumSize = isMaximumSize;
mIsInput = isInput;
mIsUltraHighResolution = isUltraHighResolution;
}
@@ -130,10 +139,12 @@ public final class MandatoryStreamCombination {
/**
* Confirms whether or not this is an ultra high resolution stream.
- * An 'ultra high resolution' stream is one which has a configuration which appears in
+ *
+ * <p>An 'ultra high resolution' stream is one which has a configuration which appears in
* {@link android.hardware.camera2.CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION},
* Streams which are ultra high resolution must not be included with streams which are not
- * ultra high resolution in the same {@link android.hardware.camera2.CaptureRequest}.
+ * ultra high resolution in the same {@link android.hardware.camera2.CaptureRequest}.</p>
+ *
* @return true in case the stream is ultra high resolution, false otherwise.
*/
public boolean isUltraHighResolution() {
@@ -141,6 +152,34 @@ public final class MandatoryStreamCombination {
}
/**
+ * Confirms whether or not this is a maximum size stream.
+ *
+ * <p>A stream with maximum size is one with the camera device's maximum resolution
+ * for the stream's format as appears in {@link
+ * android.hardware.camera2.CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP}. This
+ * maximum size has the same meaning as the 'MAXIMUM' target size documented in the camera
+ * capture session {@link CameraDevice#createCaptureSession guideline}.</p>
+ *
+ * <p>The application can use a
+ * {@link android.hardware.camera2.MultiResolutionImageReader} for a maximum size
+ * output stream if the camera device supports multi-resolution outputs for the stream's
+ * format. See {@link
+ * android.hardware.camera2.CameraCharacteristics#SCALER_MULTI_RESOLUTION_STREAM_CONFIGURATION_MAP}
+ * for details.</p>
+ *
+ * <p>This is different from the ultra high resolution flag, which applies only to
+ * ultra high resolution sensor camera devices and refers to a stream in
+ * {@link
+ * android.hardware.camera2.CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION}
+ * instead.</p>
+ *
+ * @return true if the stream is a maximum size stream.
+ */
+ public boolean isMaximumSize() {
+ return mIsMaximumSize;
+ }
+
+ /**
* Return the list of available sizes for this mandatory stream.
*
* <p>Per documented {@link CameraDevice#createCaptureSession guideline} the largest
@@ -827,7 +866,8 @@ public final class MandatoryStreamCombination {
getMaxSize(mStreamConfigMap.getOutputSizes(template.mFormat)));
sizes.add(sizeChosen);
try {
- streamInfo = new MandatoryStreamInformation(sizes, template.mFormat);
+ streamInfo = new MandatoryStreamInformation(sizes, template.mFormat,
+ /*isMaximumSize*/false);
} catch (IllegalArgumentException e) {
String cause = "No available sizes found for format: " + template.mFormat
+ " size threshold: " + template.mSizeThreshold + " combination: "
@@ -890,9 +930,11 @@ public final class MandatoryStreamCombination {
inputSize.add(maxRawInputSize);
streamsInfo.add(new MandatoryStreamInformation(inputSize,
- ImageFormat.RAW_SENSOR, /*isInput*/true, /*ultraHighResolution*/true));
+ ImageFormat.RAW_SENSOR, /*isMaximumSize*/true, /*isInput*/true,
+ /*ultraHighResolution*/true));
streamsInfo.add(new MandatoryStreamInformation(inputSize,
- ImageFormat.RAW_SENSOR, /*isInput*/ false, /*ultraHighResolution*/true));
+ ImageFormat.RAW_SENSOR, /*isMaximumSize*/true, /*isInput*/ false,
+ /*ultraHighResolution*/true));
MandatoryStreamCombination streamCombination;
streamCombination = new MandatoryStreamCombination(streamsInfo,
"Remosaic reprocessing", /*isReprocess*/true);
@@ -917,10 +959,11 @@ public final class MandatoryStreamCombination {
Size sizeChosen =
getMaxSize(streamConfigMap.getOutputSizes(
template.mFormat));
+ boolean isMaximumSize = (template.mSizeThreshold == SizeThreshold.MAXIMUM);
sizes.add(sizeChosen);
try {
streamInfo = new MandatoryStreamInformation(sizes, template.mFormat,
- /*isInput*/ false, /*ultraHighResolution*/ true);
+ isMaximumSize, /*isInput*/ false, /*ultraHighResolution*/ true);
} catch (IllegalArgumentException e) {
String cause = "No available sizes found for format: " + template.mFormat
+ " size threshold: " + template.mSizeThreshold + " combination: "
@@ -1096,8 +1139,9 @@ public final class MandatoryStreamCombination {
format = ImageFormat.YUV_420_888;
}
streamsInfo.add(new MandatoryStreamInformation(inputSize, format,
- /*isInput*/true));
- streamsInfo.add(new MandatoryStreamInformation(inputSize, format));
+ /*isMaximumSize*/true, /*isInput*/true));
+ streamsInfo.add(new MandatoryStreamInformation(inputSize, format,
+ /*isMaximumSize*/true));
}
for (StreamTemplate template : combTemplate.mStreamTemplates) {
@@ -1112,8 +1156,11 @@ public final class MandatoryStreamCombination {
}
MandatoryStreamInformation streamInfo;
+ boolean isMaximumSize =
+ (template.mSizeThreshold == SizeThreshold.MAXIMUM);
try {
- streamInfo = new MandatoryStreamInformation(sizes, template.mFormat);
+ streamInfo = new MandatoryStreamInformation(sizes, template.mFormat,
+ isMaximumSize);
} catch (IllegalArgumentException e) {
Log.e(TAG, "No available sizes found for format: " + template.mFormat +
" size threshold: " + template.mSizeThreshold + " combination: " +
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 5cfcd667632b..9198eb74d1f8 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -171,7 +171,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
SomeArgs args = (SomeArgs) msg.obj;
try {
inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1,
- (IInputMethodPrivilegedOperations) args.arg2);
+ (IInputMethodPrivilegedOperations) args.arg2, (int) args.arg3);
} finally {
args.recycle();
}
@@ -280,9 +280,10 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
public void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privOps) {
+ IInputMethodPrivilegedOperations privOps, int configChanges) {
mCaller.executeOrSendMessage(
- mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps));
+ mCaller.obtainMessageIOOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps,
+ configChanges));
}
@BinderThread
diff --git a/core/java/android/inputmethodservice/ImsConfigurationTracker.java b/core/java/android/inputmethodservice/ImsConfigurationTracker.java
new file mode 100644
index 000000000000..3c788884371b
--- /dev/null
+++ b/core/java/android/inputmethodservice/ImsConfigurationTracker.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 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.inputmethodservice;
+
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+/**
+ * Helper class that takes care of Configuration change behavior of {@link InputMethodService}.
+ * Note: this class is public for testing only. Never call any of it's methods for development
+ * of IMEs.
+ * @hide
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public final class ImsConfigurationTracker {
+
+ /**
+ * A constant value that represents {@link Configuration} has changed from the last time
+ * {@link InputMethodService#onConfigurationChanged(Configuration)} was called.
+ */
+ private static final int CONFIG_CHANGED = -1;
+
+ @Nullable
+ private Configuration mLastKnownConfig = null;
+ private int mHandledConfigChanges = 0;
+ private boolean mInitialized = false;
+
+ /**
+ * Called from {@link InputMethodService.InputMethodImpl
+ * #initializeInternal(IBinder, int, IInputMethodPrivilegedOperations, int)} ()}
+ * @param handledConfigChanges Configuration changes declared handled by IME
+ * {@link android.R.styleable#InputMethod_configChanges}.
+ */
+ @MainThread
+ public void onInitialize(int handledConfigChanges) {
+ Preconditions.checkState(!mInitialized, "onInitialize can be called only once.");
+ mInitialized = true;
+ mHandledConfigChanges = handledConfigChanges;
+ }
+
+ /**
+ * Called from {@link InputMethodService.InputMethodImpl#onBindInput()}
+ */
+ @MainThread
+ public void onBindInput(@Nullable Resources resources) {
+ Preconditions.checkState(mInitialized,
+ "onBindInput can be called only after onInitialize().");
+ if (mLastKnownConfig == null && resources != null) {
+ mLastKnownConfig = new Configuration(resources.getConfiguration());
+ }
+ }
+
+ /**
+ * Dynamically set handled configChanges.
+ * Note: this method is public for testing only.
+ */
+ public void setHandledConfigChanges(int configChanges) {
+ mHandledConfigChanges = configChanges;
+ }
+
+ /**
+ * Called from {@link InputMethodService.InputMethodImpl#onConfigurationChanged(Configuration)}}
+ */
+ @MainThread
+ public void onConfigurationChanged(@NonNull Configuration newConfig,
+ @NonNull Runnable resetStateForNewConfigurationRunner) {
+ if (!mInitialized) {
+ return;
+ }
+ final int diff = mLastKnownConfig != null
+ ? mLastKnownConfig.diffPublicOnly(newConfig) : CONFIG_CHANGED;
+ // If the new config is the same as the config this Service is already running with,
+ // then don't bother calling resetStateForNewConfiguration.
+ final int unhandledDiff = (diff & ~mHandledConfigChanges);
+ if (unhandledDiff != 0) {
+ resetStateForNewConfigurationRunner.run();
+ }
+ if (diff != 0) {
+ mLastKnownConfig = new Configuration(newConfig);
+ }
+ }
+}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 7e2be01feb01..4ee5383a56be 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -513,6 +513,7 @@ public class InputMethodService extends AbstractInputMethodService {
private boolean mIsAutomotive;
private Handler mHandler;
private boolean mImeSurfaceScheduledForRemoval;
+ private ImsConfigurationTracker mConfigTracker = new ImsConfigurationTracker();
/**
* An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
@@ -588,12 +589,13 @@ public class InputMethodService extends AbstractInputMethodService {
@MainThread
@Override
public final void initializeInternal(@NonNull IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations) {
+ IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
if (InputMethodPrivilegedOperationsRegistry.isRegistered(token)) {
Log.w(TAG, "The token has already registered, ignore this initialization.");
return;
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal");
+ mConfigTracker.onInitialize(configChanges);
mPrivOps.set(privilegedOperations);
InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps);
updateInputMethodDisplay(displayId);
@@ -663,6 +665,7 @@ public class InputMethodService extends AbstractInputMethodService {
reportFullscreenMode();
initialize();
onBindInput();
+ mConfigTracker.onBindInput(getResources());
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -938,7 +941,7 @@ public class InputMethodService extends AbstractInputMethodService {
}
private void setImeWindowStatus(int visibilityFlags, int backDisposition) {
- mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition);
+ mPrivOps.setImeWindowStatusAsync(visibilityFlags, backDisposition);
}
/** Set region of the keyboard to be avoided from back gesture */
@@ -1428,10 +1431,13 @@ public class InputMethodService extends AbstractInputMethodService {
* state: {@link #onStartInput} if input is active, and
* {@link #onCreateInputView} and {@link #onStartInputView} and related
* appropriate functions if the UI is displayed.
+ * <p>Starting with {@link Build.VERSION_CODES#S}, IMEs can opt into handling configuration
+ * changes themselves instead of being restarted with
+ * {@link android.R.styleable#InputMethod_configChanges}.
*/
@Override public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- resetStateForNewConfiguration();
+ mConfigTracker.onConfigurationChanged(newConfig, this::resetStateForNewConfiguration);
}
private void resetStateForNewConfiguration() {
@@ -3181,7 +3187,7 @@ public class InputMethodService extends AbstractInputMethodService {
requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS);
}
}
-
+
void startExtractingText(boolean inputChanged) {
final ExtractEditText eet = mExtractEditText;
if (eet != null && getCurrentInputStarted()
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 171c6a2c6a19..f50aa991a67c 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -78,5 +78,4 @@ interface INetworkPolicyManager {
boolean isUidNetworkingBlocked(int uid, boolean meteredNetwork);
boolean isUidRestrictedOnMeteredNetworks(int uid);
- boolean checkUidNetworkingBlocked(int uid, int uidRules, boolean isNetworkMetered, boolean isBackgroundRestricted);
}
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index b037261f0bc2..1eef7d9a5337 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -198,15 +198,11 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
final int oemManaged = getOemBitfield(snapshot.networkCapabilities);
if (legacyType == TYPE_WIFI) {
- if (snapshot.networkCapabilities.getSsid() != null) {
- networkId = snapshot.networkCapabilities.getSsid();
- if (networkId == null) {
- // TODO: Figure out if this code path never runs. If so, remove them.
- final WifiManager wifi = (WifiManager) context.getSystemService(
- Context.WIFI_SERVICE);
- final WifiInfo info = wifi.getConnectionInfo();
- networkId = info != null ? info.getSSID() : null;
- }
+ networkId = snapshot.networkCapabilities.getSsid();
+ if (networkId == null) {
+ final WifiManager wifi = context.getSystemService(WifiManager.class);
+ final WifiInfo info = wifi.getConnectionInfo();
+ networkId = info != null ? info.getSSID() : null;
}
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 68606ec90dc9..632eb15ecdde 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -564,31 +564,6 @@ public class NetworkPolicyManager {
}
/**
- * Figure out if networking is blocked for a given set of conditions.
- *
- * This is used by ConnectivityService via passing stale copies of conditions, so it must not
- * take any locks.
- *
- * @param uid The target uid.
- * @param uidRules The uid rules which are obtained from NetworkPolicyManagerService.
- * @param isNetworkMetered True if the network is metered.
- * @param isBackgroundRestricted True if data saver is enabled.
- *
- * @return true if networking is blocked for the UID under the specified conditions.
- *
- * @hide
- */
- public boolean checkUidNetworkingBlocked(int uid, int uidRules,
- boolean isNetworkMetered, boolean isBackgroundRestricted) {
- try {
- return mService.checkUidNetworkingBlocked(uid, uidRules, isNetworkMetered,
- isBackgroundRestricted);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Check that the given uid is restricted from doing networking on metered networks.
*
* @param uid The target uid.
@@ -794,7 +769,7 @@ public class NetworkPolicyManager {
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public static String blockedReasonsToString(int blockedReasons) {
- return DebugUtils.flagsToString(NetworkPolicyManager.class, "BLOCKED_", blockedReasons);
+ return DebugUtils.flagsToString(ConnectivityManager.class, "BLOCKED_", blockedReasons);
}
/**
diff --git a/core/java/android/net/vcn/IVcnStatusCallback.aidl b/core/java/android/net/vcn/IVcnStatusCallback.aidl
index 236ae8bb11b2..11bc443c9dd6 100644
--- a/core/java/android/net/vcn/IVcnStatusCallback.aidl
+++ b/core/java/android/net/vcn/IVcnStatusCallback.aidl
@@ -20,7 +20,7 @@ package android.net.vcn;
oneway interface IVcnStatusCallback {
void onVcnStatusChanged(int statusCode);
void onGatewayConnectionError(
- in int[] gatewayNetworkCapabilities,
+ in String gatewayConnectionName,
int errorCode,
in String exceptionClass,
in String exceptionMessage);
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index 52cc2182b094..d41c0b4fbdb3 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -183,12 +183,25 @@ public final class VcnConfig implements Parcelable {
*
* @param gatewayConnectionConfig the configuration for an individual gateway connection
* @return this {@link Builder} instance, for chaining
+ * @throws IllegalArgumentException if a VcnGatewayConnectionConfig has already been set for
+ * this {@link VcnConfig} with the same GatewayConnection name (as returned via {@link
+ * VcnGatewayConnectionConfig#getGatewayConnectionName()}).
*/
@NonNull
public Builder addGatewayConnectionConfig(
@NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
Objects.requireNonNull(gatewayConnectionConfig, "gatewayConnectionConfig was null");
+ for (final VcnGatewayConnectionConfig vcnGatewayConnectionConfig :
+ mGatewayConnectionConfigs) {
+ if (vcnGatewayConnectionConfig
+ .getGatewayConnectionName()
+ .equals(gatewayConnectionConfig.getGatewayConnectionName())) {
+ throw new IllegalArgumentException(
+ "GatewayConnection for specified name already exists");
+ }
+ }
+
mGatewayConnectionConfigs.add(gatewayConnectionConfig);
return this;
}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index d4e8e2dca296..75db3820f5e7 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -148,6 +148,8 @@ public final class VcnGatewayConnectionConfig {
TimeUnit.MINUTES.toMillis(5),
TimeUnit.MINUTES.toMillis(15)
};
+ private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName";
+ @NonNull private final String mGatewayConnectionName;
private static final String CTRL_PLANE_CONFIG_KEY = "mCtrlPlaneConfig";
@NonNull private VcnControlPlaneConfig mCtrlPlaneConfig;
@@ -166,11 +168,13 @@ public final class VcnGatewayConnectionConfig {
/** Builds a VcnGatewayConnectionConfig with the specified parameters. */
private VcnGatewayConnectionConfig(
+ @NonNull String gatewayConnectionName,
@NonNull VcnControlPlaneConfig ctrlPlaneConfig,
@NonNull Set<Integer> exposedCapabilities,
@NonNull Set<Integer> underlyingCapabilities,
@NonNull long[] retryIntervalsMs,
@IntRange(from = MIN_MTU_V6) int maxMtu) {
+ mGatewayConnectionName = gatewayConnectionName;
mCtrlPlaneConfig = ctrlPlaneConfig;
mExposedCapabilities = new TreeSet(exposedCapabilities);
mUnderlyingCapabilities = new TreeSet(underlyingCapabilities);
@@ -192,6 +196,7 @@ public final class VcnGatewayConnectionConfig {
final PersistableBundle underlyingCapsBundle =
in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
+ mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
mCtrlPlaneConfig = VcnControlPlaneConfig.fromPersistableBundle(ctrlPlaneConfigBundle);
mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
@@ -204,6 +209,7 @@ public final class VcnGatewayConnectionConfig {
}
private void validate() {
+ Objects.requireNonNull(mGatewayConnectionName, "gatewayConnectionName was null");
Objects.requireNonNull(mCtrlPlaneConfig, "control plane config was null");
Preconditions.checkArgument(
@@ -242,6 +248,20 @@ public final class VcnGatewayConnectionConfig {
}
/**
+ * Returns the configured Gateway Connection name.
+ *
+ * <p>This name is used by the configuring apps to distinguish between
+ * VcnGatewayConnectionConfigs configured on a single {@link VcnConfig}. This will be used as
+ * the identifier in VcnStatusCallback invocations.
+ *
+ * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
+ */
+ @NonNull
+ public String getGatewayConnectionName() {
+ return mGatewayConnectionName;
+ }
+
+ /**
* Returns control plane configuration.
*
* @hide
@@ -364,6 +384,7 @@ public final class VcnGatewayConnectionConfig {
new ArrayList<>(mUnderlyingCapabilities),
PersistableBundleUtils.INTEGER_SERIALIZER);
+ result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
result.putPersistableBundle(CTRL_PLANE_CONFIG_KEY, ctrlPlaneConfigBundle);
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
@@ -376,6 +397,7 @@ public final class VcnGatewayConnectionConfig {
@Override
public int hashCode() {
return Objects.hash(
+ mGatewayConnectionName,
mExposedCapabilities,
mUnderlyingCapabilities,
Arrays.hashCode(mRetryIntervalsMs),
@@ -389,7 +411,8 @@ public final class VcnGatewayConnectionConfig {
}
final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
- return mExposedCapabilities.equals(rhs.mExposedCapabilities)
+ return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
+ && mExposedCapabilities.equals(rhs.mExposedCapabilities)
&& mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
&& mMaxMtu == rhs.mMaxMtu;
@@ -399,6 +422,7 @@ public final class VcnGatewayConnectionConfig {
* This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects.
*/
public static final class Builder {
+ @NonNull private final String mGatewayConnectionName;
@NonNull private final VcnControlPlaneConfig mCtrlPlaneConfig;
@NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
@NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
@@ -412,12 +436,22 @@ public final class VcnGatewayConnectionConfig {
/**
* Construct a Builder object.
*
+ * @param gatewayConnectionName the String GatewayConnection name for this
+ * VcnGatewayConnectionConfig. Each VcnGatewayConnectionConfig within a {@link
+ * VcnConfig} must be given a unique name. This name is used by the caller to
+ * distinguish between VcnGatewayConnectionConfigs configured on a single {@link
+ * VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations.
* @param ctrlPlaneConfig the control plane configuration
* @see VcnControlPlaneConfig
+ * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
*/
- public Builder(@NonNull VcnControlPlaneConfig ctrlPlaneConfig) {
+ public Builder(
+ @NonNull String gatewayConnectionName,
+ @NonNull VcnControlPlaneConfig ctrlPlaneConfig) {
+ Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null");
Objects.requireNonNull(ctrlPlaneConfig, "ctrlPlaneConfig was null");
+ mGatewayConnectionName = gatewayConnectionName;
mCtrlPlaneConfig = ctrlPlaneConfig;
}
@@ -562,6 +596,7 @@ public final class VcnGatewayConnectionConfig {
@NonNull
public VcnGatewayConnectionConfig build() {
return new VcnGatewayConnectionConfig(
+ mGatewayConnectionName,
mCtrlPlaneConfig,
mExposedCapabilities,
mUnderlyingCapabilities,
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index abd41dacdeb6..344b20c036a0 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -437,7 +437,7 @@ public class VcnManager {
* Invoked when status of the VCN for this callback's subscription group changes.
*
* @param statusCode the code for the status change encountered by this {@link
- * VcnStatusCallback}'s subscription group.
+ * VcnStatusCallback}'s subscription group. This value will be one of VCN_STATUS_CODE_*.
*/
public abstract void onStatusChanged(@VcnStatusCode int statusCode);
@@ -445,18 +445,17 @@ public class VcnManager {
* Invoked when a VCN Gateway Connection corresponding to this callback's subscription group
* encounters an error.
*
- * @param networkCapabilities an array of NetworkCapabilities.NET_CAPABILITY_* capabilities
- * for the Gateway Connection that encountered the error, for identification purposes.
- * These will be a sorted list with no duplicates and will match {@link
- * VcnGatewayConnectionConfig#getExposedCapabilities()} for one of the {@link
- * VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
- * group.
- * @param errorCode the code to indicate the error that occurred
+ * @param gatewayConnectionName the String GatewayConnection name for the GatewayConnection
+ * encountering an error. This will match the name for exactly one {@link
+ * VcnGatewayConnectionConfig} for the {@link VcnConfig} configured for this callback's
+ * subscription group
+ * @param errorCode the code to indicate the error that occurred. This value will be one of
+ * VCN_ERROR_CODE_*.
* @param detail Throwable to provide additional information about the error, or {@code
* null} if none
*/
public abstract void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable Throwable detail);
}
@@ -586,7 +585,7 @@ public class VcnManager {
// TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
@Override
public void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable String exceptionClass,
@Nullable String exceptionMessage) {
@@ -597,7 +596,7 @@ public class VcnManager {
mExecutor.execute(
() ->
mCallback.onGatewayConnectionError(
- networkCapabilities, errorCode, cause)));
+ gatewayConnectionName, errorCode, cause)));
}
private static Throwable createThrowableByClassName(
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 2b6f336848c3..033148379041 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -124,6 +124,30 @@ public abstract class BatteryConsumer {
public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
+ /**
+ * Identifiers of models used for power estimation.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"POWER_MODEL_"}, value = {
+ POWER_MODEL_POWER_PROFILE,
+ POWER_MODEL_MEASURED_ENERGY,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PowerModel {
+ }
+
+ /**
+ * Power model that is based on average consumption rates that hardware components
+ * consume in various states.
+ */
+ public static final int POWER_MODEL_POWER_PROFILE = 0;
+
+ /**
+ * Power model that is based on energy consumption measured by on-device power monitors.
+ */
+ public static final int POWER_MODEL_MEASURED_ENERGY = 1;
+
private final PowerComponents mPowerComponents;
protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
@@ -149,6 +173,16 @@ public abstract class BatteryConsumer {
}
/**
+ * Returns the ID of the model that was used for power estimation.
+ *
+ * @param componentId The ID of the power component, e.g.
+ * {@link BatteryConsumer#POWER_COMPONENT_CPU}.
+ */
+ public @PowerModel int getPowerModel(@BatteryConsumer.PowerComponent int componentId) {
+ return mPowerComponents.getPowerModel(componentId);
+ }
+
+ /**
* Returns the amount of drain attributed to the specified custom drain type.
*
* @param componentId The ID of the custom power component.
@@ -188,9 +222,10 @@ public abstract class BatteryConsumer {
protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
final PowerComponents.Builder mPowerComponentsBuilder;
- public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount) {
+ public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels) {
mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
- customTimeComponentCount);
+ customTimeComponentCount, includePowerModels);
}
/**
@@ -200,10 +235,23 @@ public abstract class BatteryConsumer {
* {@link BatteryConsumer#POWER_COMPONENT_CPU}.
* @param componentPower Amount of consumed power in mAh.
*/
- @SuppressWarnings("unchecked")
@NonNull
public T setConsumedPower(@PowerComponent int componentId, double componentPower) {
- mPowerComponentsBuilder.setConsumedPower(componentId, componentPower);
+ return setConsumedPower(componentId, componentPower, POWER_MODEL_POWER_PROFILE);
+ }
+
+ /**
+ * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
+ *
+ * @param componentId The ID of the power component, e.g.
+ * {@link BatteryConsumer#POWER_COMPONENT_CPU}.
+ * @param componentPower Amount of consumed power in mAh.
+ */
+ @SuppressWarnings("unchecked")
+ @NonNull
+ public T setConsumedPower(@PowerComponent int componentId, double componentPower,
+ @PowerModel int powerModel) {
+ mPowerComponentsBuilder.setConsumedPower(componentId, componentPower, powerModel);
return (T) this;
}
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index a0721c32fc2a..f2887748f460 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -74,7 +74,7 @@ public final class BatteryUsageStats implements Parcelable {
for (int i = 0; i < systemBatteryConsumerCount; i++) {
final SystemBatteryConsumer consumer =
builder.mSystemBatteryConsumerBuilders.valueAt(i).build();
- totalPower += consumer.getConsumedPower();
+ totalPower += consumer.getConsumedPower() - consumer.getPowerConsumedByApps();
mSystemBatteryConsumers.add(consumer);
}
@@ -261,6 +261,7 @@ public final class BatteryUsageStats implements Parcelable {
public static final class Builder {
private final int mCustomPowerComponentCount;
private final int mCustomTimeComponentCount;
+ private final boolean mIncludePowerModels;
private long mStatsStartTimestampMs;
private int mDischargePercentage;
private double mDischargedPowerLowerBoundMah;
@@ -277,8 +278,14 @@ public final class BatteryUsageStats implements Parcelable {
private List<BatteryStats.HistoryTag> mHistoryTagPool;
public Builder(int customPowerComponentCount, int customTimeComponentCount) {
+ this(customPowerComponentCount, customTimeComponentCount, false);
+ }
+
+ public Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels) {
mCustomPowerComponentCount = customPowerComponentCount;
mCustomTimeComponentCount = customTimeComponentCount;
+ mIncludePowerModels = includePowerModels;
}
/**
@@ -360,7 +367,7 @@ public final class BatteryUsageStats implements Parcelable {
UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
if (builder == null) {
builder = new UidBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, batteryStatsUid);
+ mCustomTimeComponentCount, mIncludePowerModels, batteryStatsUid);
mUidBatteryConsumerBuilders.put(uid, builder);
}
return builder;
@@ -376,7 +383,7 @@ public final class BatteryUsageStats implements Parcelable {
SystemBatteryConsumer.Builder builder = mSystemBatteryConsumerBuilders.get(drainType);
if (builder == null) {
builder = new SystemBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, drainType);
+ mCustomTimeComponentCount, mIncludePowerModels, drainType);
mSystemBatteryConsumerBuilders.put(drainType, builder);
}
return builder;
@@ -391,7 +398,7 @@ public final class BatteryUsageStats implements Parcelable {
UserBatteryConsumer.Builder builder = mUserBatteryConsumerBuilders.get(userId);
if (builder == null) {
builder = new UserBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, userId);
+ mCustomTimeComponentCount, mIncludePowerModels, userId);
mUserBatteryConsumerBuilders.put(userId, builder);
}
return builder;
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index 85861bc1d2aa..50804422e92f 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -60,6 +60,12 @@ public final class BatteryUsageStatsQuery implements Parcelable {
*/
public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY = 2;
+ /**
+ * Indicates that identifiers of power models used for computations of power
+ * consumption should be included in the BatteryUsageStats.
+ */
+ public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS = 4;
+
private static final long DEFAULT_MAX_STATS_AGE_MS = 5 * 60 * 1000;
private final int mFlags;
@@ -187,6 +193,17 @@ public final class BatteryUsageStatsQuery implements Parcelable {
}
/**
+ * Requests to return identifiers of models that were used for estimation
+ * of power consumption.
+ *
+ * Should only be used for testing and debugging.
+ */
+ public Builder includePowerModels() {
+ mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS;
+ return this;
+ }
+
+ /**
* Set the client's tolerance for stale battery stats. The data may be up to
* this many milliseconds out-of-date.
*/
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index a2edc93c6e5e..8adb79b60ffd 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -117,15 +117,20 @@ public class Build {
public static final String HARDWARE = getString("ro.hardware");
/**
- * The SKU of the hardware (from the kernel command line). The SKU is reported by the bootloader
- * to configure system software features.
+ * The SKU of the hardware (from the kernel command line).
+ *
+ * <p>The SKU is reported by the bootloader to configure system software features.
+ * If no value is supplied by the bootloader, this is reported as {@link #UNKNOWN}.
+
*/
@NonNull
public static final String SKU = getString("ro.boot.hardware.sku");
/**
- * The SKU of the device as set by the original design manufacturer (ODM). This is a
- * runtime-initialized property set during startup to configure device services.
+ * The SKU of the device as set by the original design manufacturer (ODM).
+ *
+ * <p>This is a runtime-initialized property set during startup to configure device
+ * services. If no value is set, this is reported as {@link #UNKNOWN}.
*
* <p>The ODM SKU may have multiple variants for the same system SKU in case a manufacturer
* produces variants of the same design. For example, the same build may be released with
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index b12dad038ce3..40c658f01e28 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -46,8 +46,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
-import android.content.res.AssetFileDescriptor;
-import android.net.Uri;
import android.provider.DocumentsContract.Document;
import android.provider.MediaStore;
import android.system.ErrnoException;
@@ -83,7 +81,6 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
-import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -1446,46 +1443,22 @@ public final class FileUtils {
}
}
- // TODO(b/170488060): Consider better approach
/** {@hide} */
@VisibleForTesting
- public static FileDescriptor convertToModernFd(FileDescriptor fd) {
+ public static ParcelFileDescriptor convertToModernFd(FileDescriptor fd) {
try {
Context context = AppGlobals.getInitialApplication();
- // /mnt/user paths are not accessible directly so convert to a /storage path
- String filePath = Os.readlink("/proc/self/fd/" + fd.getInt$()).replace(
- "/mnt/user/" + UserHandle.myUserId(), "/storage");
- File realFile = new File(filePath);
- String fileName = realFile.getName();
- boolean isCameraVideo = !fileName.startsWith(".") && fileName.endsWith(".mp4")
- && contains(CAMERA_DIR_LOWER_CASE, filePath.toLowerCase(Locale.ROOT));
-
- if (!SystemProperties.getBoolean("sys.fuse.transcode_enabled", false)
- || UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)
- || !isCameraVideo) {
- // 1. If transcode is enabled we optimize by default, unless explicitly disabled.
- // 2. Never convert modern fd for MediaProvider, because this requires
+ if (UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
+ // Never convert modern fd for MediaProvider, because this requires
// MediaStore#scanFile and can cause infinite loops when MediaProvider scans
- // 3. Only convert published mp4 videos in the DCIM/Camera dir
return null;
}
- Log.i(TAG, "Changing to modern format dataSource for: " + realFile);
- ContentResolver resolver = context.getContentResolver();
-
- Uri uri = MediaStore.scanFile(resolver, realFile);
- if (uri != null) {
- Bundle opts = new Bundle();
- opts.putBoolean(MediaStore.EXTRA_ACCEPT_ORIGINAL_MEDIA_FORMAT, true);
- AssetFileDescriptor afd = resolver.openTypedAssetFileDescriptor(uri, "*/*", opts);
- Log.i(TAG, "Changed to modern format dataSource for: " + realFile);
- return afd.getFileDescriptor();
- } else {
- Log.i(TAG, "Failed to change to modern format dataSource for: " + realFile);
- }
+ return MediaStore.getOriginalMediaFormatFileDescriptor(context,
+ ParcelFileDescriptor.dup(fd));
} catch (Exception e) {
- Log.w(TAG, "Failed to change to modern format dataSource", e);
+ Log.w(TAG, "Failed to convert to modern format file descriptor", e);
+ return null;
}
- return null;
}
private static int getMediaProviderAppId(Context context) {
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index d239b23b6ff6..238f4518b7d3 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -33,12 +33,14 @@ class PowerComponents {
private final double[] mPowerComponentsMah;
private final long[] mTimeComponentsMs;
private final int mCustomPowerComponentCount;
+ private final byte[] mPowerModels;
PowerComponents(@NonNull Builder builder) {
mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
mPowerComponentsMah = builder.mPowerComponentsMah;
mTimeComponentsMs = builder.mTimeComponentsMs;
mTotalConsumedPowerMah = builder.getTotalPower();
+ mPowerModels = builder.mPowerModels;
}
PowerComponents(@NonNull Parcel source) {
@@ -46,6 +48,12 @@ class PowerComponents {
mCustomPowerComponentCount = source.readInt();
mPowerComponentsMah = source.createDoubleArray();
mTimeComponentsMs = source.createLongArray();
+ if (source.readBoolean()) {
+ mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
+ source.readByteArray(mPowerModels);
+ } else {
+ mPowerModels = null;
+ }
}
/** Writes contents to Parcel */
@@ -54,6 +62,12 @@ class PowerComponents {
dest.writeInt(mCustomPowerComponentCount);
dest.writeDoubleArray(mPowerComponentsMah);
dest.writeLongArray(mTimeComponentsMs);
+ if (mPowerModels != null) {
+ dest.writeBoolean(true);
+ dest.writeByteArray(mPowerModels);
+ } else {
+ dest.writeBoolean(false);
+ }
}
/**
@@ -103,6 +117,15 @@ class PowerComponents {
}
}
+ @BatteryConsumer.PowerModel
+ int getPowerModel(@BatteryConsumer.PowerComponent int component) {
+ if (mPowerModels == null) {
+ throw new IllegalStateException(
+ "Power model IDs were not requested in the BatteryUsageStatsQuery");
+ }
+ return mPowerModels[component];
+ }
+
/**
* Returns the amount of time used by the specified component, e.g. CPU, WiFi etc.
*
@@ -148,14 +171,21 @@ class PowerComponents {
private final double[] mPowerComponentsMah;
private final int mCustomPowerComponentCount;
private final long[] mTimeComponentsMs;
+ private final byte[] mPowerModels;
- Builder(int customPowerComponentCount, int customTimeComponentCount) {
+ Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels) {
mCustomPowerComponentCount = customPowerComponentCount;
int powerComponentCount =
BatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount;
mPowerComponentsMah = new double[powerComponentCount];
mTimeComponentsMs =
new long[BatteryConsumer.TIME_COMPONENT_COUNT + customTimeComponentCount];
+ if (includePowerModels) {
+ mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
+ } else {
+ mPowerModels = null;
+ }
}
/**
@@ -167,7 +197,7 @@ class PowerComponents {
*/
@NonNull
public Builder setConsumedPower(@BatteryConsumer.PowerComponent int componentId,
- double componentPower) {
+ double componentPower, @BatteryConsumer.PowerModel int powerModel) {
if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
@@ -178,6 +208,9 @@ class PowerComponents {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
}
+ if (mPowerModels != null) {
+ mPowerModels[componentId] = (byte) powerModel;
+ }
return this;
}
diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java
index 5f35332f4818..e973e4c1044e 100644
--- a/core/java/android/os/SystemBatteryConsumer.java
+++ b/core/java/android/os/SystemBatteryConsumer.java
@@ -141,8 +141,8 @@ public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
Builder(int customPowerComponentCount, int customTimeComponentCount,
- @DrainType int drainType) {
- super(customPowerComponentCount, customTimeComponentCount);
+ boolean includePowerModels, @DrainType int drainType) {
+ super(customPowerComponentCount, customTimeComponentCount, includePowerModels);
mDrainType = drainType;
}
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index 841aad556d6a..5d8190213119 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -199,6 +199,16 @@ public class SystemVibratorManager extends VibratorManager {
return mVibratorInfo.hasAmplitudeControl();
}
+ @Override
+ public float getResonantFrequency() {
+ return mVibratorInfo.getResonantFrequency();
+ }
+
+ @Override
+ public float getQFactor() {
+ return mVibratorInfo.getQFactor();
+ }
+
@NonNull
@Override
public int[] areEffectsSupported(@NonNull int... effectIds) {
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index dfa0c396485d..87c263b3dd38 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -140,8 +140,8 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
private boolean mExcludeFromBatteryUsageStats;
public Builder(int customPowerComponentCount, int customTimeComponentCount,
- @NonNull BatteryStats.Uid batteryStatsUid) {
- super(customPowerComponentCount, customTimeComponentCount);
+ boolean includePowerModels, @NonNull BatteryStats.Uid batteryStatsUid) {
+ super(customPowerComponentCount, customTimeComponentCount, includePowerModels);
mBatteryStatsUid = batteryStatsUid;
mUid = batteryStatsUid.getUid();
}
diff --git a/core/java/android/os/UserBatteryConsumer.java b/core/java/android/os/UserBatteryConsumer.java
index 94e567f368b0..78322088a3a4 100644
--- a/core/java/android/os/UserBatteryConsumer.java
+++ b/core/java/android/os/UserBatteryConsumer.java
@@ -77,8 +77,9 @@ public class UserBatteryConsumer extends BatteryConsumer implements Parcelable {
private final int mUserId;
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
- Builder(int customPowerComponentCount, int customTimeComponentCount, int userId) {
- super(customPowerComponentCount, customTimeComponentCount);
+ Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels, int userId) {
+ super(customPowerComponentCount, customTimeComponentCount, includePowerModels);
mUserId = userId;
}
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 047c05a8734b..7fb9ae0d86cc 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -25,6 +25,7 @@ import android.content.pm.DataLoaderParams;
import android.content.pm.IPackageLoadingProgressCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -285,7 +286,7 @@ public final class IncrementalManager {
* Unbinds the target dir and deletes the corresponding storage instance.
* Deletes the package name and associated storage id from maps.
*/
- public void onPackageRemoved(@NonNull File codeFile) {
+ public void rmPackageDir(@NonNull File codeFile) {
try {
final String codePath = codeFile.getAbsolutePath();
final IncrementalStorage storage = openStorage(codePath);
@@ -294,11 +295,9 @@ public final class IncrementalManager {
}
mLoadingProgressCallbacks.cleanUpCallbacks(storage);
unregisterHealthListener(codePath);
-
- // Parent since we bind-mount a folder one level above.
- mService.deleteBindMount(storage.getId(), codeFile.getParent());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ storage.unBind(codePath);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to remove code path", e);
}
}
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 6d677f35b563..66e1c5a93f16 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -48,4 +48,10 @@ oneway interface IPermissionController {
void getPrivilegesDescriptionStringForProfile(
in String deviceProfileName,
in AndroidFuture<String> callback);
+ void getPlatformPermissionsForGroup(
+ in String permissionGroupName,
+ in AndroidFuture<List<String>> callback);
+ void getGroupOfPlatformPermission(
+ in String permissionName,
+ in AndroidFuture<String> callback);
}
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 913b827332bf..05eb23ad705d 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -45,6 +45,7 @@ import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
@@ -66,6 +67,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -720,4 +722,46 @@ public final class PermissionControllerManager {
mRemoteService.run(
service -> service.notifyOneTimePermissionSessionTimeout(packageName));
}
+
+ /**
+ * Get the platform permissions which belong to a particular permission group
+ *
+ * @param permissionGroupName The permission group whose permissions are desired
+ * @return A list of the platform permissions in the group, or empty if the group is not a valid
+ * platform group.
+ */
+ public @NonNull Set<String> getPlatformPermissionsForGroup(
+ @NonNull String permissionGroupName) {
+ try {
+ return new ArraySet<>(mRemoteService.postAsync(service -> {
+ AndroidFuture<List<String>> future = new AndroidFuture<>();
+ service.getPlatformPermissionsForGroup(permissionGroupName, future);
+ return future;
+ }).get(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get permissions of " + permissionGroupName, e);
+ return null;
+ }
+ }
+
+ /**
+ * Get the platform group of a particular permission, if the permission is a platform permission
+ *
+ * @param permissionName The permission name whose group is desired
+ * @return The name of the permission group this permission belongs to, or null if it has no
+ * group, or is not a platform permission
+ */
+ public @Nullable String getGroupOfPlatformPermission(
+ @NonNull String permissionName) {
+ try {
+ return mRemoteService.postAsync(service -> {
+ AndroidFuture<String> future = new AndroidFuture<>();
+ service.getGroupOfPlatformPermission(permissionName, future);
+ return future;
+ }).get(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get group of " + permissionName, e);
+ return null;
+ }
+ }
}
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index ad9e8b3d6dd4..0b99b85fdf24 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -301,6 +301,29 @@ public abstract class PermissionControllerService extends Service {
}
/**
+ * Get the platform permissions which belong to a particular permission group
+ *
+ * @param permissionGroupName The permission group whose permissions are desired
+ * @param callback A callback the permission names will be passed to
+ */
+ @BinderThread
+ public void onGetPlatformPermissionsForGroup(@NonNull String permissionGroupName,
+ @NonNull Consumer<List<String>> callback) {
+ throw new AbstractMethodError("Must be overridden in implementing class");
+ }
+
+ /**
+ * Get the platform group of a particular permission, if the permission is a platform permission
+ *
+ * @param permissionName The permission name whose group is desired
+ * @param callback A callback the group name will be passed to
+ */
+ @BinderThread
+ public void onGetGroupOfPlatformPermission(@NonNull String permissionName,
+ @NonNull Consumer<String> callback) {
+ throw new AbstractMethodError("Must be overridden in implementing class");
+ }
+ /**
* Get a user-readable sentence, describing the set of privileges that are to be granted to a
* companion app managing a device of the given profile.
*
@@ -563,6 +586,36 @@ public abstract class PermissionControllerService extends Service {
callback.completeExceptionally(t);
}
}
+
+ @Override
+ public void getPlatformPermissionsForGroup(
+ @NonNull String permissionName,
+ @NonNull AndroidFuture<List<String>> callback) {
+ try {
+ Objects.requireNonNull(permissionName);
+ Objects.requireNonNull(callback);
+ PermissionControllerService.this.onGetPlatformPermissionsForGroup(
+ permissionName, callback::complete);
+ } catch (Throwable t) {
+ callback.completeExceptionally(t);
+ }
+ }
+
+ @Override
+ public void getGroupOfPlatformPermission(
+ @NonNull String permissionGroupName,
+ @NonNull AndroidFuture<String> callback) {
+ try {
+ Objects.requireNonNull(permissionGroupName);
+ Objects.requireNonNull(callback);
+ PermissionControllerService
+ .this
+ .onGetGroupOfPlatformPermission(
+ permissionGroupName, callback::complete);
+ } catch (Throwable t) {
+ callback.completeExceptionally(t);
+ }
+ }
};
}
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 936cbfc70708..751e9aafdf09 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -1114,6 +1114,7 @@ public final class PermissionManager {
*
* @hide
*/
+ @TestApi
public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
try {
return mPermissionManager.registerAttributionSource(source);
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 03b5a2e2568a..d7d1902b9b9f 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -800,10 +800,24 @@ public final class DeviceConfig {
}
/**
- * Reset properties to their default values.
+ * Reset properties to their default values by removing the underlying values.
* <p>
* The method accepts an optional namespace parameter. If provided, only properties set within
* that namespace will be reset. Otherwise, all properties will be reset.
+ * <p>
+ * Note: This method should only be used by {@link com.android.server.RescueParty}. It was
+ * designed to be used in the event of boot or crash loops caused by flag changes. It does not
+ * revert flag values to defaults - instead it removes the property entirely which causes the
+ * consumer of the flag to use hardcoded defaults upon retrieval.
+ * <p>
+ * To clear values for a namespace without removing the underlying properties, construct a
+ * {@link Properties} object with the caller's namespace and either an empty flag map, or some
+ * snapshot of flag values. Then use {@link #setProperties(Properties)} to remove all flags
+ * under the namespace, or set them to the values in the snapshot.
+ * <p>
+ * To revert values for testing, one should mock DeviceConfig using
+ * {@link com.android.server.testables.TestableDeviceConfig} where possible. Otherwise, fallback
+ * to using {@link #setProperties(Properties)} as outlined above.
*
* @param resetMode The reset mode to use.
* @param namespace Optionally, the specific namespace which resets will be limited to.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 94384e9578e8..5093b95b5297 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -471,10 +471,9 @@ public final class Settings {
* <p>
* Output: Nothing.
*/
- @SuppressLint("ActionValue")
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_APP_OPEN_BY_DEFAULT_SETTINGS =
- "com.android.settings.APP_OPEN_BY_DEFAULT_SETTINGS";
+ "android.settings.APP_OPEN_BY_DEFAULT_SETTINGS";
/**
* Activity Action: Show trusted credentials settings, opening to the user tab,
@@ -6756,9 +6755,8 @@ public final class Settings {
/**
* The current location time zone detection enabled state for the user.
*
- * See {@link
- * android.app.timezonedetector.TimeZoneDetector#getCapabilities} for access. See {@link
- * android.app.timezonedetector.TimeZoneDetector#updateConfiguration} to update.
+ * See {@link android.app.time.TimeManager#getTimeZoneCapabilitiesAndConfig} for access.
+ * See {@link android.app.time.TimeManager#updateTimeZoneConfiguration} to update.
* @hide
*/
public static final String LOCATION_TIME_ZONE_DETECTION_ENABLED =
diff --git a/core/java/android/security/ConfirmationPrompt.java b/core/java/android/security/ConfirmationPrompt.java
index 232903724d82..d8c44adcc322 100644
--- a/core/java/android/security/ConfirmationPrompt.java
+++ b/core/java/android/security/ConfirmationPrompt.java
@@ -21,7 +21,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
-import android.security.keystore.AndroidKeyStoreProvider;
import android.text.TextUtils;
import android.util.Log;
@@ -106,32 +105,6 @@ public class ConfirmationPrompt {
private void doCallback(int responseCode, byte[] dataThatWasConfirmed,
ConfirmationCallback callback) {
switch (responseCode) {
- case KeyStore.CONFIRMATIONUI_OK:
- callback.onConfirmed(dataThatWasConfirmed);
- break;
-
- case KeyStore.CONFIRMATIONUI_CANCELED:
- callback.onDismissed();
- break;
-
- case KeyStore.CONFIRMATIONUI_ABORTED:
- callback.onCanceled();
- break;
-
- case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR:
- callback.onError(new Exception("System error returned by ConfirmationUI."));
- break;
-
- default:
- callback.onError(new Exception("Unexpected responseCode=" + responseCode
- + " from onConfirmtionPromptCompleted() callback."));
- break;
- }
- }
-
- private void doCallback2(int responseCode, byte[] dataThatWasConfirmed,
- ConfirmationCallback callback) {
- switch (responseCode) {
case AndroidProtectedConfirmation.ERROR_OK:
callback.onConfirmed(dataThatWasConfirmed);
break;
@@ -155,31 +128,6 @@ public class ConfirmationPrompt {
}
}
- private final android.os.IBinder mCallbackBinder =
- new android.security.IConfirmationPromptCallback.Stub() {
- @Override
- public void onConfirmationPromptCompleted(
- int responseCode, final byte[] dataThatWasConfirmed)
- throws android.os.RemoteException {
- if (mCallback != null) {
- ConfirmationCallback callback = mCallback;
- Executor executor = mExecutor;
- mCallback = null;
- mExecutor = null;
- if (executor == null) {
- doCallback(responseCode, dataThatWasConfirmed, callback);
- } else {
- executor.execute(new Runnable() {
- @Override
- public void run() {
- doCallback(responseCode, dataThatWasConfirmed, callback);
- }
- });
- }
- }
- }
- };
-
private final android.security.apc.IConfirmationCallback mConfirmationCallback =
new android.security.apc.IConfirmationCallback.Stub() {
@Override
@@ -191,11 +139,11 @@ public class ConfirmationPrompt {
mCallback = null;
mExecutor = null;
if (executor == null) {
- doCallback2(result, dataThatWasConfirmed, callback);
+ doCallback(result, dataThatWasConfirmed, callback);
} else {
executor.execute(new Runnable() {
@Override public void run() {
- doCallback2(result, dataThatWasConfirmed, callback);
+ doCallback(result, dataThatWasConfirmed, callback);
}
});
}
@@ -266,29 +214,7 @@ public class ConfirmationPrompt {
mExtraData = extraData;
}
- private static final int UI_OPTION_ACCESSIBILITY_INVERTED_FLAG = 1 << 0;
- private static final int UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG = 1 << 1;
-
private int getUiOptionsAsFlags() {
- if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
- return getUiOptionsAsFlags2();
- }
- int uiOptionsAsFlags = 0;
- ContentResolver contentResolver = mContext.getContentResolver();
- int inversionEnabled = Settings.Secure.getInt(contentResolver,
- Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0);
- if (inversionEnabled == 1) {
- uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_INVERTED_FLAG;
- }
- float fontScale = Settings.System.getFloat(contentResolver,
- Settings.System.FONT_SCALE, (float) 1.0);
- if (fontScale > 1.0) {
- uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG;
- }
- return uiOptionsAsFlags;
- }
-
- private int getUiOptionsAsFlags2() {
int uiOptionsAsFlags = 0;
ContentResolver contentResolver = mContext.getContentResolver();
int inversionEnabled = Settings.Secure.getInt(contentResolver,
@@ -349,52 +275,26 @@ public class ConfirmationPrompt {
mExecutor = executor;
String locale = Locale.getDefault().toLanguageTag();
- if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
- int uiOptionsAsFlags = getUiOptionsAsFlags2();
- int responseCode = getService().presentConfirmationPrompt(
- mConfirmationCallback, mPromptText.toString(), mExtraData, locale,
- uiOptionsAsFlags);
- switch (responseCode) {
- case AndroidProtectedConfirmation.ERROR_OK:
- return;
-
- case AndroidProtectedConfirmation.ERROR_OPERATION_PENDING:
- throw new ConfirmationAlreadyPresentingException();
-
- case AndroidProtectedConfirmation.ERROR_UNIMPLEMENTED:
- throw new ConfirmationNotAvailableException();
-
- default:
- // Unexpected error code.
- Log.w(TAG,
- "Unexpected responseCode=" + responseCode
- + " from presentConfirmationPrompt() call.");
- throw new IllegalArgumentException();
- }
- } else {
- int uiOptionsAsFlags = getUiOptionsAsFlags();
- int responseCode = mKeyStore.presentConfirmationPrompt(
- mCallbackBinder, mPromptText.toString(), mExtraData, locale, uiOptionsAsFlags);
- switch (responseCode) {
- case KeyStore.CONFIRMATIONUI_OK:
- return;
-
- case KeyStore.CONFIRMATIONUI_OPERATION_PENDING:
- throw new ConfirmationAlreadyPresentingException();
+ int uiOptionsAsFlags = getUiOptionsAsFlags();
+ int responseCode = getService().presentConfirmationPrompt(
+ mConfirmationCallback, mPromptText.toString(), mExtraData, locale,
+ uiOptionsAsFlags);
+ switch (responseCode) {
+ case AndroidProtectedConfirmation.ERROR_OK:
+ return;
- case KeyStore.CONFIRMATIONUI_UNIMPLEMENTED:
- throw new ConfirmationNotAvailableException();
+ case AndroidProtectedConfirmation.ERROR_OPERATION_PENDING:
+ throw new ConfirmationAlreadyPresentingException();
- case KeyStore.CONFIRMATIONUI_UIERROR:
- throw new IllegalArgumentException();
+ case AndroidProtectedConfirmation.ERROR_UNIMPLEMENTED:
+ throw new ConfirmationNotAvailableException();
- default:
- // Unexpected error code.
- Log.w(TAG,
- "Unexpected responseCode=" + responseCode
- + " from presentConfirmationPrompt() call.");
- throw new IllegalArgumentException();
- }
+ default:
+ // Unexpected error code.
+ Log.w(TAG,
+ "Unexpected responseCode=" + responseCode
+ + " from presentConfirmationPrompt() call.");
+ throw new IllegalArgumentException();
}
}
@@ -408,33 +308,18 @@ public class ConfirmationPrompt {
* @throws IllegalStateException if no prompt is currently being presented.
*/
public void cancelPrompt() {
- if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
- int responseCode =
- getService().cancelConfirmationPrompt(mConfirmationCallback);
- if (responseCode == AndroidProtectedConfirmation.ERROR_OK) {
- return;
- } else if (responseCode == AndroidProtectedConfirmation.ERROR_OPERATION_PENDING) {
- throw new IllegalStateException();
- } else {
- // Unexpected error code.
- Log.w(TAG,
- "Unexpected responseCode=" + responseCode
- + " from cancelConfirmationPrompt() call.");
- throw new IllegalStateException();
- }
+ int responseCode =
+ getService().cancelConfirmationPrompt(mConfirmationCallback);
+ if (responseCode == AndroidProtectedConfirmation.ERROR_OK) {
+ return;
+ } else if (responseCode == AndroidProtectedConfirmation.ERROR_OPERATION_PENDING) {
+ throw new IllegalStateException();
} else {
- int responseCode = mKeyStore.cancelConfirmationPrompt(mCallbackBinder);
- if (responseCode == KeyStore.CONFIRMATIONUI_OK) {
- return;
- } else if (responseCode == KeyStore.CONFIRMATIONUI_OPERATION_PENDING) {
- throw new IllegalStateException();
- } else {
- // Unexpected error code.
- Log.w(TAG,
- "Unexpected responseCode=" + responseCode
- + " from cancelConfirmationPrompt() call.");
- throw new IllegalStateException();
- }
+ // Unexpected error code.
+ Log.w(TAG,
+ "Unexpected responseCode=" + responseCode
+ + " from cancelConfirmationPrompt() call.");
+ throw new IllegalStateException();
}
}
@@ -448,9 +333,6 @@ public class ConfirmationPrompt {
if (isAccessibilityServiceRunning(context)) {
return false;
}
- if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
- return new AndroidProtectedConfirmation().isConfirmationPromptSupported();
- }
- return KeyStore.getInstance().isConfirmationPromptSupported();
+ return new AndroidProtectedConfirmation().isConfirmationPromptSupported();
}
}
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
new file mode 100644
index 000000000000..e01db7acce99
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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.security.keymaster;
+
+parcelable KeymasterCertificateChain;
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index 6788353ba2fb..ad9b79606455 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -712,18 +712,10 @@ public class RecoveryController {
*/
@NonNull Key getKeyFromGrant(@NonNull String grantAlias)
throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
- if (grantAlias.startsWith(APPLICATION_KEY_GRANT_PREFIX)) {
- return AndroidKeyStoreProvider
- .loadAndroidKeyStoreSecretKeyFromKeystore(
- KeyStore2.getInstance(),
- getGrantDescriptor(grantAlias));
- }
- // TODO(b/171305545): remove KeyStore1 logic.
- return android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
- mKeyStore,
- grantAlias,
- KeyStore.UID_SELF);
-
+ return AndroidKeyStoreProvider
+ .loadAndroidKeyStoreSecretKeyFromKeystore(
+ KeyStore2.getInstance(),
+ getGrantDescriptor(grantAlias));
}
private static final String APPLICATION_KEY_GRANT_PREFIX = "recoverable_key:";
diff --git a/core/java/android/service/notification/NotificationListenerFilter.java b/core/java/android/service/notification/NotificationListenerFilter.java
index 9de75cac159a..a69d33c17e9d 100644
--- a/core/java/android/service/notification/NotificationListenerFilter.java
+++ b/core/java/android/service/notification/NotificationListenerFilter.java
@@ -31,15 +31,17 @@ import android.util.ArraySet;
* @hide
*/
public class NotificationListenerFilter implements Parcelable {
+
+ private static final int DEFAULT_TYPES = FLAG_FILTER_TYPE_CONVERSATIONS
+ | FLAG_FILTER_TYPE_ALERTING
+ | FLAG_FILTER_TYPE_SILENT
+ | FLAG_FILTER_TYPE_ONGOING;
private int mAllowedNotificationTypes;
// VersionedPackage is holding the pkg name and pkg uid
private ArraySet<VersionedPackage> mDisallowedPackages;
public NotificationListenerFilter() {
- mAllowedNotificationTypes = FLAG_FILTER_TYPE_CONVERSATIONS
- | FLAG_FILTER_TYPE_ALERTING
- | FLAG_FILTER_TYPE_SILENT
- | FLAG_FILTER_TYPE_ONGOING;
+ mAllowedNotificationTypes = DEFAULT_TYPES;
mDisallowedPackages = new ArraySet<>();
}
@@ -80,6 +82,10 @@ public class NotificationListenerFilter implements Parcelable {
return (mAllowedNotificationTypes & type) != 0;
}
+ public boolean areAllTypesAllowed() {
+ return DEFAULT_TYPES == mAllowedNotificationTypes;
+ }
+
public boolean isPackageAllowed(VersionedPackage pkg) {
return !mDisallowedPackages.contains(pkg);
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 09c3b2effcb0..6c775852fcee 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -792,6 +792,29 @@ public abstract class NotificationListenerService extends Service {
}
}
+ /**
+ * Lets an app migrate notification filters from its app into the OS.
+ *
+ * <p>This call will be ignored if the app has already migrated these settings or the user
+ * has set filters in the UI. This method is intended for user specific settings; if an app has
+ * already specified defaults types in its manifest with
+ * {@link #META_DATA_DEFAULT_FILTER_TYPES}, the defaultTypes option will be ignored.</p>
+ * @param defaultTypes A value representing the types of notifications that this listener should
+ * receive by default
+ * @param disallowedPkgs A list of package names whose notifications should not be seen by this
+ * listener, by default, because the listener does not process or display them, or because a
+ * user had previously disallowed these packages in the listener app's UI
+ */
+ public final void migrateNotificationFilter(@NotificationFilterTypes int defaultTypes,
+ @Nullable List<String> disallowedPkgs) {
+ if (!isBound()) return;
+ try {
+ getNotificationInterface().migrateNotificationFilter(
+ mWrapper, defaultTypes, disallowedPkgs);
+ } catch (android.os.RemoteException ex) {
+ Log.v(TAG, "Unable to contact notification manager", ex);
+ }
+ }
/**
* Inform the notification manager that these notifications have been viewed by the
diff --git a/core/java/android/service/rotationresolver/RotationResolutionRequest.java b/core/java/android/service/rotationresolver/RotationResolutionRequest.java
index 8dec0922b097..8c7db4003235 100644
--- a/core/java/android/service/rotationresolver/RotationResolutionRequest.java
+++ b/core/java/android/service/rotationresolver/RotationResolutionRequest.java
@@ -50,7 +50,7 @@ public final class RotationResolutionRequest implements Parcelable {
/** The proposed screen rotation in the system. */
@Surface.Rotation private final int mProposedRotation;
- /** Whether should use camera signal to resolver rotation. */
+ /** Whether should use the camera sensor to resolve screen rotation. */
private final boolean mShouldUseCamera;
/** The timeout of the request. */
@@ -59,7 +59,7 @@ public final class RotationResolutionRequest implements Parcelable {
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -82,7 +82,7 @@ public final class RotationResolutionRequest implements Parcelable {
* @param proposedRotation
* The proposed screen rotation in the system.
* @param shouldUseCamera
- * Whether should use camera signal to resolver rotation.
+ * Whether should use the camera sensor to resolve screen rotation.
* @param timeoutMillis
* The timeout of the request.
*/
@@ -135,7 +135,7 @@ public final class RotationResolutionRequest implements Parcelable {
}
/**
- * Whether should use camera signal to resolver rotation.
+ * Whether should use the camera sensor to resolve screen rotation.
*/
@DataClass.Generated.Member
public boolean shouldUseCamera() {
@@ -230,8 +230,8 @@ public final class RotationResolutionRequest implements Parcelable {
};
@DataClass.Generated(
- time = 1615402421314L,
- codegenVersion = "1.0.22",
+ time = 1617213094231L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/rotationresolver/RotationResolutionRequest.java",
inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.view.Surface.Rotation int mCurrentRotation\nprivate final @android.view.Surface.Rotation int mProposedRotation\nprivate final boolean mShouldUseCamera\nprivate final @android.annotation.DurationMillisLong long mTimeoutMillis\nclass RotationResolutionRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genToString=true)")
@Deprecated
diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS
new file mode 100644
index 000000000000..32f482264103
--- /dev/null
+++ b/core/java/android/speech/OWNERS
@@ -0,0 +1,3 @@
+volnov@google.com
+eugeniom@google.com
+schfan@google.com
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 0cbcb16762f8..42e9bfdae809 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -214,6 +214,17 @@ public class SpeechRecognizer {
* command to the created {@code SpeechRecognizer}, otherwise no notifications will be
* received.
*
+ * <p>For apps targeting Android 11 (API level 30) interaction with a speech recognition
+ * service requires <queries> element to be added to the manifest file:
+ * <pre>{@code
+ * <queries>
+ * <intent>
+ * <action
+ * android:name="android.speech.RecognitionService" />
+ * </intent>
+ * </queries>
+ * }</pre>
+ *
* @param context in which to create {@code SpeechRecognizer}
* @return a new {@code SpeechRecognizer}
*/
@@ -231,7 +242,18 @@ public class SpeechRecognizer {
* {@link SpeechRecognizer} to. Normally you would not use this; use
* {@link #createSpeechRecognizer(Context)} instead to use the system default recognition
* service.
- *
+ *
+ * <p>For apps targeting Android 11 (API level 30) interaction with a speech recognition
+ * service requires <queries> element to be added to the manifest file:
+ * <pre>{@code
+ * <queries>
+ * <intent>
+ * <action
+ * android:name="android.speech.RecognitionService" />
+ * </intent>
+ * </queries>
+ * }</pre>
+ *
* @param context in which to create {@code SpeechRecognizer}
* @param serviceComponent the {@link ComponentName} of a specific service to direct this
* {@code SpeechRecognizer} to
diff --git a/core/java/android/text/method/TranslationTransformationMethod.java b/core/java/android/text/method/TranslationTransformationMethod.java
index 54c0ffcdbb65..7db999a89fbe 100644
--- a/core/java/android/text/method/TranslationTransformationMethod.java
+++ b/core/java/android/text/method/TranslationTransformationMethod.java
@@ -78,11 +78,24 @@ public class TranslationTransformationMethod implements TransformationMethod2 {
if (TextUtils.isEmpty(translatedText) || isWhitespace(translatedText.toString())) {
return source;
} else {
+ // TODO(b/179693024): Remove this once we have the fix to pad the view text instead.
+ translatedText = ellipsize(translatedText, ((TextView) view).getText().length());
// TODO(b/174283799): apply the spans to the text
return translatedText;
}
}
+ private static CharSequence ellipsize(CharSequence text, int newLength) {
+ if (text.length() <= newLength) {
+ return text;
+ }
+ String ellipsis = String.valueOf('\u2026');
+ if (newLength == 1) {
+ return ellipsis;
+ }
+ return TextUtils.concat(TextUtils.trimToSize(text, newLength - 1), ellipsis);
+ }
+
@Override
public void onFocusChanged(View view, CharSequence sourceText,
boolean focused, int direction,
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 913ceae63a94..572e50a8ce34 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -70,7 +70,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put("settings_tether_all_in_one", "false");
DEFAULT_FLAGS.put("settings_silky_home", "true");
DEFAULT_FLAGS.put("settings_contextual_home", "false");
- DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "false");
+ DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "true");
DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "false");
}
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index 2a43222b9e48..78c4739968e3 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -61,7 +61,10 @@ public final class Slog {
* of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
* calling this method in a critical path, make sure to explicitly do the check before calling
* it.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void v(String tag, String format, @Nullable Object... args) {
if (!Log.isLoggable(tag, Log.VERBOSE)) return;
@@ -87,7 +90,10 @@ public final class Slog {
* of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
* calling this method in a critical path, make sure to explicitly do the check before calling
* it.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void d(String tag, String format, @Nullable Object... args) {
if (!Log.isLoggable(tag, Log.DEBUG)) return;
@@ -112,7 +118,10 @@ public final class Slog {
* of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
* calling this method in a critical path, make sure to explicitly do the check before calling
* it.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void i(String tag, String format, @Nullable Object... args) {
if (!Log.isLoggable(tag, Log.INFO)) return;
@@ -142,7 +151,10 @@ public final class Slog {
* of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
* calling this method in a critical path, make sure to explicitly do the check before calling
* it.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void w(String tag, String format, @Nullable Object... args) {
if (!Log.isLoggable(tag, Log.WARN)) return;
@@ -157,7 +169,10 @@ public final class Slog {
* of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
* calling this method in a critical path, make sure to explicitly do the check before calling
* it.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void w(String tag, Exception exception, String format, @Nullable Object... args) {
if (!Log.isLoggable(tag, Log.WARN)) return;
@@ -183,7 +198,10 @@ public final class Slog {
* of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
* calling this method in a critical path, make sure to explicitly do the check before calling
* it.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void e(String tag, String format, @Nullable Object... args) {
if (!Log.isLoggable(tag, Log.ERROR)) return;
@@ -198,7 +216,10 @@ public final class Slog {
* of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
* calling this method in a critical path, make sure to explicitly do the check before calling
* it.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void e(String tag, Exception exception, String format, @Nullable Object... args) {
if (!Log.isLoggable(tag, Log.ERROR)) return;
@@ -217,14 +238,20 @@ public final class Slog {
/**
* Logs a {@code wtf} message.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void wtf(String tag, String format, @Nullable Object... args) {
wtf(tag, getMessage(format, args));
}
/**
* Logs a {@code wtf} message with an exception.
+ *
+ * @deprecated use {@code com.android.server.utils.SLogF} instead.
*/
+ @Deprecated
public static void wtf(String tag, Exception exception, String format,
@Nullable Object... args) {
wtf(tag, getMessage(format, args), exception);
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index cd6585cd3fa1..5fd0c33ca205 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -30,6 +30,7 @@ import com.android.i18n.timezone.ZoneInfoDb;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
+import java.time.Instant;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Calendar;
@@ -43,11 +44,39 @@ import java.util.List;
public class TimeUtils {
/** @hide */ public TimeUtils() {}
/** {@hide} */
- private static SimpleDateFormat sLoggingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private static final SimpleDateFormat sLoggingFormat =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/** @hide */
public static final SimpleDateFormat sDumpDateFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+
+ /**
+ * This timestamp is used in TimeUtils methods and by the SettingsUI to filter time zones
+ * to only "effective" ones in a country. It is compared against the notUsedAfter metadata that
+ * Android records for some time zones.
+ *
+ * <p>What is notUsedAfter?</p>
+ * Android chooses to avoid making users choose between functionally identical time zones at the
+ * expense of not being able to represent local times in the past.
+ *
+ * notUsedAfter exists because some time zones can "merge" with other time zones after a given
+ * point in time (i.e. they change to have identical transitions, offsets, display names, etc.).
+ * From the notUsedAfter time, the zone will express the same local time as the one it merged
+ * with.
+ *
+ * <p>Why hardcoded?</p>
+ * Rather than using System.currentTimeMillis(), a timestamp known to be in the recent past is
+ * used to ensure consistent behavior across devices and time, and avoid assumptions that the
+ * system clock on a device is currently set correctly. The fixed value should be updated
+ * occasionally, but it doesn't have to be very often as effective time zones for a country
+ * don't change very often.
+ *
+ * @hide
+ */
+ public static final Instant MIN_USE_DATE_OF_TIMEZONE =
+ Instant.ofEpochMilli(1546300800000L); // 1/1/2019 00:00 UTC
+
/**
* Tries to return a time zone that would have had the specified offset
* and DST value at the specified moment in the specified country.
@@ -109,7 +138,7 @@ public class TimeUtils {
List<String> timeZoneIds = new ArrayList<>();
for (TimeZoneMapping timeZoneMapping : countryTimeZones.getTimeZoneMappings()) {
- if (timeZoneMapping.isShownInPicker()) {
+ if (timeZoneMapping.isShownInPickerAt(MIN_USE_DATE_OF_TIMEZONE)) {
timeZoneIds.add(timeZoneMapping.getTimeZoneId());
}
}
diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java
index 85f2c1ccc180..5c7f0f5cb1e0 100644
--- a/core/java/android/uwb/RangingManager.java
+++ b/core/java/android/uwb/RangingManager.java
@@ -17,6 +17,7 @@
package android.uwb;
import android.annotation.NonNull;
+import android.content.AttributionSource;
import android.os.CancellationSignal;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -42,6 +43,9 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
/**
* Open a new ranging session
*
+ * @param attributionSource Attribution source to use for the enforcement of
+ * {@link android.Manifest.permission#ULTRAWIDEBAND_RANGING} runtime
+ * permission.
* @param params the parameters that define the ranging session
* @param executor {@link Executor} to run callbacks
* @param callbacks {@link RangingSession.Callback} to associate with the {@link RangingSession}
@@ -49,7 +53,8 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
* @return a {@link CancellationSignal} that may be used to cancel the opening of the
* {@link RangingSession}.
*/
- public CancellationSignal openSession(@NonNull PersistableBundle params,
+ public CancellationSignal openSession(@NonNull AttributionSource attributionSource,
+ @NonNull PersistableBundle params,
@NonNull Executor executor,
@NonNull RangingSession.Callback callbacks) {
synchronized (this) {
@@ -58,6 +63,7 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
new RangingSession(executor, callbacks, mAdapter, sessionHandle);
mRangingSessionTable.put(sessionHandle, session);
try {
+ // TODO: Pass in the attributionSource to the service.
mAdapter.openRanging(sessionHandle, this, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index 844bbbe7970b..bed77e664337 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -16,7 +16,7 @@
package android.uwb;
-import android.Manifest;
+import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -24,7 +24,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.content.AttributionSource;
import android.content.Context;
+import android.content.ContextParams;
import android.os.CancellationSignal;
import android.os.IBinder;
import android.os.PersistableBundle;
@@ -47,9 +49,10 @@ import java.util.concurrent.Executor;
@SystemApi
@SystemService(Context.UWB_SERVICE)
public final class UwbManager {
- private IUwbAdapter mUwbAdapter;
private static final String SERVICE_NAME = "uwb";
+ private final Context mContext;
+ private final IUwbAdapter mUwbAdapter;
private final AdapterStateListener mAdapterStateListener;
private final RangingManager mRangingManager;
@@ -116,9 +119,11 @@ public final class UwbManager {
/**
* Use <code>Context.getSystemService(UwbManager.class)</code> to get an instance.
*
+ * @param ctx Context of the client.
* @param adapter an instance of an {@link android.uwb.IUwbAdapter}
*/
- private UwbManager(IUwbAdapter adapter) {
+ private UwbManager(@NonNull Context ctx, @NonNull IUwbAdapter adapter) {
+ mContext = ctx;
mUwbAdapter = adapter;
mAdapterStateListener = new AdapterStateListener(adapter);
mRangingManager = new RangingManager(adapter);
@@ -127,7 +132,7 @@ public final class UwbManager {
/**
* @hide
*/
- public static UwbManager getInstance() {
+ public static UwbManager getInstance(@NonNull Context ctx) {
IBinder b = ServiceManager.getService(SERVICE_NAME);
if (b == null) {
return null;
@@ -138,7 +143,7 @@ public final class UwbManager {
return null;
}
- return new UwbManager(adapter);
+ return new UwbManager(ctx, adapter);
}
/**
@@ -153,7 +158,7 @@ public final class UwbManager {
* @param executor an {@link Executor} to execute given callback
* @param callback user implementation of the {@link AdapterStateCallback}
*/
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
+ @RequiresPermission(permission.UWB_PRIVILEGED)
public void registerAdapterStateCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull AdapterStateCallback callback) {
mAdapterStateListener.register(executor, callback);
@@ -168,7 +173,7 @@ public final class UwbManager {
*
* @param callback user implementation of the {@link AdapterStateCallback}
*/
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
+ @RequiresPermission(permission.UWB_PRIVILEGED)
public void unregisterAdapterStateCallback(@NonNull AdapterStateCallback callback) {
mAdapterStateListener.unregister(callback);
}
@@ -182,7 +187,7 @@ public final class UwbManager {
* @return {@link PersistableBundle} of the device's supported UWB protocols and parameters
*/
@NonNull
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
+ @RequiresPermission(permission.UWB_PRIVILEGED)
public PersistableBundle getSpecificationInfo() {
try {
return mUwbAdapter.getSpecificationInfo();
@@ -199,7 +204,7 @@ public final class UwbManager {
* @return the timestamp resolution in nanoseconds
*/
@SuppressLint("MethodNameUnits")
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
+ @RequiresPermission(permission.UWB_PRIVILEGED)
public long elapsedRealtimeResolutionNanos() {
try {
return mUwbAdapter.getTimestampResolutionNanos();
@@ -235,10 +240,14 @@ public final class UwbManager {
* {@link RangingSession.Callback#onOpened(RangingSession)}.
*/
@NonNull
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ permission.UWB_PRIVILEGED,
+ permission.UWB_RANGING
+ })
public CancellationSignal openRangingSession(@NonNull PersistableBundle parameters,
@NonNull @CallbackExecutor Executor executor,
@NonNull RangingSession.Callback callbacks) {
- return mRangingManager.openSession(parameters, executor, callbacks);
+ return mRangingManager.openSession(
+ mContext.getAttributionSource(), parameters, executor, callbacks);
}
}
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index c62e93463048..9f63500fc853 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -129,6 +129,12 @@ public class HapticFeedbackConstants {
public static final int SAFE_MODE_ENABLED = 10001;
/**
+ * Invocation of the voice assistant via hardware button.
+ * @hide
+ */
+ public static final int ASSISTANT_BUTTON = 10002;
+
+ /**
* Flag for {@link View#performHapticFeedback(int, int)
* View.performHapticFeedback(int, int)}: Ignore the setting in the
* view for whether to perform haptic feedback, do it always.
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 0812cdcb7c0a..f28242aa8215 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -55,6 +55,8 @@ public abstract class InputEventReceiver {
InputChannel inputChannel, MessageQueue messageQueue);
private static native void nativeDispose(long receiverPtr);
private static native void nativeFinishInputEvent(long receiverPtr, int seq, boolean handled);
+ private static native void nativeReportTimeline(long receiverPtr, int inputEventId,
+ long gpuCompletedTime, long presentTime);
private static native boolean nativeConsumeBatchedInputEvents(long receiverPtr,
long frameTimeNanos);
private static native String nativeDump(long receiverPtr, String prefix);
@@ -210,11 +212,11 @@ public abstract class InputEventReceiver {
}
/**
- * Report the latency information for a specific input event.
+ * Report the timing / latency information for a specific input event.
*/
- public final void reportLatencyInfo(int inputEventId, long gpuCompletedTime, long presentTime) {
- Trace.traceBegin(Trace.TRACE_TAG_INPUT, "reportLatencyInfo");
- // TODO(b/169866723) : send this data to InputDispatcher via InputChannel
+ public final void reportTimeline(int inputEventId, long gpuCompletedTime, long presentTime) {
+ Trace.traceBegin(Trace.TRACE_TAG_INPUT, "reportTimeline");
+ nativeReportTimeline(mReceiverPtr, inputEventId, gpuCompletedTime, presentTime);
Trace.traceEnd(Trace.TRACE_TAG_INPUT);
}
diff --git a/core/java/android/view/InputEventSender.java b/core/java/android/view/InputEventSender.java
index 40eb438262a1..d14421897860 100644
--- a/core/java/android/view/InputEventSender.java
+++ b/core/java/android/view/InputEventSender.java
@@ -112,6 +112,16 @@ public abstract class InputEventSender {
}
/**
+ * Called when timeline is sent to the publisher.
+ *
+ * @param inputEventId The id of the input event that caused the frame being reported
+ * @param gpuCompletedTime The time when the frame left the app process
+ * @param presentTime The time when the frame was presented on screen
+ */
+ public void onTimelineReported(int inputEventId, long gpuCompletedTime, long presentTime) {
+ }
+
+ /**
* Sends an input event.
* Must be called on the same Looper thread to which the sender is attached.
*
@@ -143,4 +153,11 @@ public abstract class InputEventSender {
private void dispatchInputEventFinished(int seq, boolean handled) {
onInputEventFinished(seq, handled);
}
+
+ // Called from native code.
+ @SuppressWarnings("unused")
+ private void dispatchTimelineReported(
+ int inputEventId, long gpuCompletedTime, long presentTime) {
+ onTimelineReported(inputEventId, gpuCompletedTime, presentTime);
+ }
}
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 3d1c8ff515c7..f487c6c61973 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -34,6 +34,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.graphics.Insets;
@@ -808,7 +809,7 @@ public class InsetsState implements Parcelable {
dest.writeTypedObject(mRoundedCorners, flags);
}
- public static final @android.annotation.NonNull Creator<InsetsState> CREATOR = new Creator<InsetsState>() {
+ public static final @NonNull Creator<InsetsState> CREATOR = new Creator<InsetsState>() {
public InsetsState createFromParcel(Parcel in) {
return new InsetsState(in);
@@ -842,5 +843,16 @@ public class InsetsState implements Parcelable {
+ ", mSources= { " + joiner
+ " }";
}
+
+ public @NonNull String toSourceVisibilityString() {
+ StringJoiner joiner = new StringJoiner(", ");
+ for (int i = 0; i < SIZE; i++) {
+ InsetsSource source = mSources[i];
+ if (source != null) {
+ joiner.add(typeToString(i) + ": " + (source.isVisible() ? "visible" : "invisible"));
+ }
+ }
+ return joiner.toString();
+ }
}
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 4a1d68547f70..cdf1e46ac5db 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -59,6 +59,10 @@ per-file ViewRootImpl.java = file:/services/core/java/com/android/server/input/O
per-file ViewRootImpl.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file ViewRootImpl.java = file:/core/java/android/view/inputmethod/OWNERS
per-file AccessibilityInteractionController.java = file:/services/accessibility/OWNERS
+per-file OnReceiveContentListener.java = file:/core/java/android/service/autofill/OWNERS
+per-file OnReceiveContentListener.java = file:/core/java/android/widget/OWNERS
+per-file ContentInfo.java = file:/core/java/android/service/autofill/OWNERS
+per-file ContentInfo.java = file:/core/java/android/widget/OWNERS
# WindowManager
per-file DisplayCutout.aidl = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index 14dcdad8e2b5..cdc099b8e2ea 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -34,7 +34,8 @@ import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import android.annotation.IntDef;
-import android.app.PictureInPictureParams;
+import android.app.ActivityManager;
+import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Point;
@@ -189,12 +190,11 @@ public class RemoteAnimationTarget implements Parcelable {
public boolean isNotInRecents;
/**
- * {@link PictureInPictureParams} to allow launcher to determine if an app should
- * automatically enter PiP on swiping up to home.
+ * {@link TaskInfo} to allow the controller to identify information about the task.
*
* TODO: add this to proto dump
*/
- public PictureInPictureParams pictureInPictureParams;
+ public ActivityManager.RunningTaskInfo taskInfo;
/**
* The {@link android.view.WindowManager.LayoutParams.WindowType} of this window. It's only used
@@ -206,11 +206,10 @@ public class RemoteAnimationTarget implements Parcelable {
Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
Rect localBounds, Rect screenSpaceBounds,
WindowConfiguration windowConfig, boolean isNotInRecents,
- SurfaceControl startLeash, Rect startBounds,
- PictureInPictureParams pictureInPictureParams) {
+ SurfaceControl startLeash, Rect startBounds, ActivityManager.RunningTaskInfo taskInfo) {
this(taskId, mode, leash, isTranslucent, clipRect, contentInsets, prefixOrderIndex,
position, localBounds, screenSpaceBounds, windowConfig, isNotInRecents, startLeash,
- startBounds, pictureInPictureParams, INVALID_WINDOW_TYPE);
+ startBounds, taskInfo, INVALID_WINDOW_TYPE);
}
public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
@@ -218,7 +217,7 @@ public class RemoteAnimationTarget implements Parcelable {
Rect localBounds, Rect screenSpaceBounds,
WindowConfiguration windowConfig, boolean isNotInRecents,
SurfaceControl startLeash, Rect startBounds,
- PictureInPictureParams pictureInPictureParams,
+ ActivityManager.RunningTaskInfo taskInfo,
@WindowManager.LayoutParams.WindowType int windowType) {
this.mode = mode;
this.taskId = taskId;
@@ -235,7 +234,7 @@ public class RemoteAnimationTarget implements Parcelable {
this.isNotInRecents = isNotInRecents;
this.startLeash = startLeash;
this.startBounds = startBounds == null ? null : new Rect(startBounds);
- this.pictureInPictureParams = pictureInPictureParams;
+ this.taskInfo = taskInfo;
this.windowType = windowType;
}
@@ -255,7 +254,7 @@ public class RemoteAnimationTarget implements Parcelable {
isNotInRecents = in.readBoolean();
startLeash = in.readTypedObject(SurfaceControl.CREATOR);
startBounds = in.readTypedObject(Rect.CREATOR);
- pictureInPictureParams = in.readTypedObject(PictureInPictureParams.CREATOR);
+ taskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
windowType = in.readInt();
}
@@ -281,7 +280,7 @@ public class RemoteAnimationTarget implements Parcelable {
dest.writeBoolean(isNotInRecents);
dest.writeTypedObject(startLeash, 0 /* flags */);
dest.writeTypedObject(startBounds, 0 /* flags */);
- dest.writeTypedObject(pictureInPictureParams, 0 /* flags */);
+ dest.writeTypedObject(taskInfo, 0 /* flags */);
dest.writeInt(windowType);
}
@@ -299,7 +298,7 @@ public class RemoteAnimationTarget implements Parcelable {
pw.println();
pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration);
pw.print(prefix); pw.print("leash="); pw.println(leash);
- pw.print(prefix); pw.print("pictureInPictureParams="); pw.println(pictureInPictureParams);
+ pw.print(prefix); pw.print("taskInfo="); pw.println(taskInfo);
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 65b8afa4e27f..48a0e80d9464 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -99,7 +99,7 @@ public class Surface implements Parcelable {
private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
private static native int nativeSetFrameRate(
- long nativeObject, float frameRate, int compatibility, boolean shouldBeSeamless);
+ long nativeObject, float frameRate, int compatibility, int changeFrameRateStrategy);
public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
new Parcelable.Creator<Surface>() {
@@ -228,6 +228,26 @@ public class Surface implements Parcelable {
*/
public static final int FRAME_RATE_COMPATIBILITY_EXACT = 100;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"CHANGE_FRAME_RATE_"},
+ value = {CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, CHANGE_FRAME_RATE_ALWAYS})
+ public @interface ChangeFrameRateStrategy {}
+
+ /**
+ * Change the frame rate only if the transition is going to be seamless.
+ */
+ public static final int CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS = 0;
+
+ /**
+ * Change the frame rate even if the transition is going to be non-seamless, i.e. with visual
+ * interruptions for the user. Non-seamless switches might be used when the benefit of matching
+ * the content's frame rate outweighs the cost of the transition, for example when
+ * displaying long-running video content.
+ */
+ public static final int CHANGE_FRAME_RATE_ALWAYS = 1;
+
/**
* Create an empty surface, which will later be filled in by readFromParcel().
* @hide
@@ -945,25 +965,21 @@ public class Surface implements Parcelable {
* the display at 60fps.
*
* @param compatibility The frame rate compatibility of this surface. The
- * compatibility value may influence the system's choice of display frame rate. See
- * the FRAME_RATE_COMPATIBILITY_* values for more info.
+ * compatibility value may influence the system's choice of display frame rate.
*
- * @param shouldBeSeamless Whether display refresh rate transitions should be seamless. A
+ * @param changeFrameRateStrategy Whether display refresh rate transitions should be seamless. A
* seamless transition is one that doesn't have any visual interruptions, such as a black
- * screen for a second or two. True indicates that any frame rate changes caused by this
- * request should be seamless. False indicates that non-seamless refresh rates are also
- * acceptable. Non-seamless switches might be used when the benefit of matching the content's
- * frame rate outweighs the cost of the transition, for example when displaying
- * long-running video content.
+ * screen for a second or two.
*
* @throws IllegalArgumentException If frameRate or compatibility are invalid.
*/
public void setFrameRate(@FloatRange(from = 0.0) float frameRate,
- @FrameRateCompatibility int compatibility, boolean shouldBeSeamless) {
+ @FrameRateCompatibility int compatibility,
+ @ChangeFrameRateStrategy int changeFrameRateStrategy) {
synchronized (mLock) {
checkNotReleasedLocked();
int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility,
- shouldBeSeamless);
+ changeFrameRateStrategy);
if (error == -EINVAL) {
throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()");
} else if (error != 0) {
@@ -976,11 +992,11 @@ public class Surface implements Parcelable {
* Sets the intended frame rate for this surface. Any switching of refresh rates is
* most probably going to be seamless.
*
- * @see #setFrameRate(float, int, boolean)
+ * @see #setFrameRate(float, int, int)
*/
public void setFrameRate(
@FloatRange(from = 0.0) float frameRate, @FrameRateCompatibility int compatibility) {
- setFrameRate(frameRate, compatibility, /* shouldBeSeamless = */ true);
+ setFrameRate(frameRate, compatibility, CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
}
/**
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index fd8bdfd5b0b0..7a9cfd4737ab 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -211,7 +211,7 @@ public final class SurfaceControl implements Parcelable {
@Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius);
private static native void nativeSetFrameRate(long transactionObj, long nativeObject,
- float frameRate, int compatibility, boolean shouldBeSeamless);
+ float frameRate, int compatibility, int changeFrameRateStrategy);
private static native long nativeGetHandle(long nativeObject);
private static native long nativeAcquireFrameRateFlexibilityToken();
@@ -3268,13 +3268,14 @@ public final class SurfaceControl implements Parcelable {
* Sets the intended frame rate for this surface. Any switching of refresh rates is
* most probably going to be seamless.
*
- * @see #setFrameRate(SurfaceControl, float, int, boolean)
+ * @see #setFrameRate(SurfaceControl, float, int, int)
*/
@NonNull
public Transaction setFrameRate(@NonNull SurfaceControl sc,
@FloatRange(from = 0.0) float frameRate,
@Surface.FrameRateCompatibility int compatibility) {
- return setFrameRate(sc, frameRate, compatibility, /*shouldBeSeamless*/ true);
+ return setFrameRate(sc, frameRate, compatibility,
+ Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
}
/**
@@ -3295,27 +3296,21 @@ public final class SurfaceControl implements Parcelable {
* refresh rate for this device's display - e.g., it's fine to pass 30fps
* to a device that can only run the display at 60fps.
* @param compatibility The frame rate compatibility of this surface. The compatibility
- * value may influence the system's choice of display frame rate. See
- * the Surface.FRAME_RATE_COMPATIBILITY_* values for more info.
- * @param shouldBeSeamless Whether display refresh rate transitions should be seamless. A
- * seamless transition is one that doesn't have any visual
- * interruptions, such as a black screen for a second or two. True
- * indicates that any frame rate changes caused by this request
- * should be seamless. False indicates that non-seamless refresh
- * rates are also acceptable. Non-seamless switches might be
- * used when the benefit of matching the content's frame rate
- * outweighs the cost of the transition, for example when
- * displaying long-running video content.
+ * value may influence the system's choice of display frame rate.
+ * @param changeFrameRateStrategy Whether display refresh rate transitions should be
+ * seamless. A seamless transition is one that doesn't have
+ * any visual interruptions, such as a black screen for a
+ * second or two.
* @return This transaction object.
*/
@NonNull
public Transaction setFrameRate(@NonNull SurfaceControl sc,
@FloatRange(from = 0.0) float frameRate,
@Surface.FrameRateCompatibility int compatibility,
- boolean shouldBeSeamless) {
+ @Surface.ChangeFrameRateStrategy int changeFrameRateStrategy) {
checkPreconditions(sc);
nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate, compatibility,
- shouldBeSeamless);
+ changeFrameRateStrategy);
return this;
}
diff --git a/core/java/android/view/SurfaceControlHdrLayerInfoListener.java b/core/java/android/view/SurfaceControlHdrLayerInfoListener.java
new file mode 100644
index 000000000000..13d68d021e31
--- /dev/null
+++ b/core/java/android/view/SurfaceControlHdrLayerInfoListener.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2021 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.view;
+
+import android.annotation.RequiresPermission;
+import android.os.IBinder;
+import android.util.ArrayMap;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.util.Objects;
+
+/**
+ * Allows for the monitoring of layers with HDR content
+ *
+ * @hide */
+public abstract class SurfaceControlHdrLayerInfoListener {
+ private static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ SurfaceControlHdrLayerInfoListener.class.getClassLoader(), nGetDestructor());
+
+ /**
+ * Callback when the HDR information about the given display has changed
+ *
+ * @param displayToken The display this callback is about
+ * @param numberOfHdrLayers How many HDR layers are visible on the display
+ * @param maxW The width of the HDR layer with the largest area
+ * @param maxH The height of the HDR layer with the largest area
+ * @param flags Additional metadata flags, currently always 0
+ * TODO(b/182312559): Add some flags
+ *
+ * @hide */
+ public abstract void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers,
+ int maxW, int maxH, int flags);
+
+ /**
+ * Registers this as an HDR info listener on the provided display
+ * @param displayToken
+ */
+ @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+ public void register(IBinder displayToken) {
+ Objects.requireNonNull(displayToken);
+ synchronized (this) {
+ if (mRegisteredListeners.containsKey(displayToken)) {
+ return;
+ }
+ long nativePtr = nRegister(displayToken);
+ Runnable destructor = sRegistry.registerNativeAllocation(this, nativePtr);
+ mRegisteredListeners.put(displayToken, destructor);
+ }
+ }
+
+ /**
+ * Unregisters this as an HDR info listener on the provided display
+ * @param displayToken
+ */
+ @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+ public void unregister(IBinder displayToken) {
+ Objects.requireNonNull(displayToken);
+ final Runnable destructor;
+ synchronized (this) {
+ destructor = mRegisteredListeners.remove(displayToken);
+ }
+ if (destructor != null) {
+ destructor.run();
+ }
+ }
+
+ /**
+ * Unregisters this on all previously registered displays
+ */
+ @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+ public void unregisterAll() {
+ final ArrayMap<IBinder, Runnable> toDestroy;
+ synchronized (this) {
+ toDestroy = mRegisteredListeners;
+ mRegisteredListeners = new ArrayMap<>();
+ }
+ for (Runnable destructor : toDestroy.values()) {
+ destructor.run();
+ }
+ }
+
+ private ArrayMap<IBinder, Runnable> mRegisteredListeners = new ArrayMap<>();
+
+ private static native long nGetDestructor();
+ private native long nRegister(IBinder displayToken);
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 840b69de3054..ec69d1cc6a2b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5255,7 +5255,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
@Nullable
- private String[] mOnReceiveContentMimeTypes;
+ private String[] mReceiveContentMimeTypes;
@Nullable
private ViewTranslationCallback mViewTranslationCallback;
@@ -8847,7 +8847,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setAutofillValue(getAutofillValue());
}
structure.setImportantForAutofill(getImportantForAutofill());
- structure.setOnReceiveContentMimeTypes(getOnReceiveContentMimeTypes());
+ structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
}
int ignoredParentLeft = 0;
@@ -9066,7 +9066,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
Preconditions.checkArgument(Arrays.stream(mimeTypes).noneMatch(t -> t.startsWith("*")),
"A MIME type set here must not start with *: " + Arrays.toString(mimeTypes));
}
- mOnReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
+ mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
getListenerInfo().mOnReceiveContentListener = listener;
}
@@ -9134,8 +9134,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@SuppressLint("NullableCollection")
@Nullable
- public String[] getOnReceiveContentMimeTypes() {
- return mOnReceiveContentMimeTypes;
+ public String[] getReceiveContentMimeTypes() {
+ return mReceiveContentMimeTypes;
}
/**
@@ -19786,6 +19786,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return;
}
+ if (mAttachInfo == null) {
+ // View is not attached.
+ return;
+ }
+
final int h = dr.getIntrinsicHeight();
final int w = dr.getIntrinsicWidth();
final Rect rect = mAttachInfo.mTmpInvalRect;
@@ -29547,6 +29552,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return mScrollCaptureInternal;
}
+ ViewRoot getViewRoot() {
+ return mViewRootImpl;
+ }
+
public void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
writer.println(prefix + "AttachInfo:");
@@ -30759,10 +30768,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* view.
* @param supportedFormats the supported translation formats. For now, the only possible value
* is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
- * @param requestsCollector a {@link ViewTranslationRequest} collector that will be called
+ * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
* multiple times to collect the information to be translated in the virtual view. One
* {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
- * contains the {@link AutofillId} corresponding to the virtualChildIds.
+ * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
+ * Consumer after the method returns.
*/
@SuppressLint("NullableCollection")
public void onCreateTranslationRequests(@NonNull long[] virtualChildIds,
@@ -30835,7 +30845,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* ui translation, the system will call this method to traverse the view hierarchy to call
* {@link View#onCreateTranslationRequest} to build {@link ViewTranslationRequest}s and create a
* {@link android.view.translation.Translator} to translate the requests. All the
- * {@link ViewTranslationRequest}s will be added when the traversal is done.
+ * {@link ViewTranslationRequest}s must be added when the traversal is done.
*
* <p> The default implementation will call {@link View#onCreateTranslationRequest} to build
* {@link ViewTranslationRequest} if the view should be translated. </p>
@@ -30934,4 +30944,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
}
}
+
+ /**
+ * @return The {@link android.view.ViewRoot} interface for this View. This will only
+ * return a non-null value when called between {@link #onAttachedToWindow} and
+ * {@link #onDetachedFromWindow}.
+ *
+ * The ViewRoot itself is not a View, it is just the interface to the windowing-system
+ * object that contains the entire view hierarchy. For the root View of a given hierarchy
+ * see {@link #getRootView}.
+ */
+ public @Nullable ViewRoot getViewRoot() {
+ if (mAttachInfo != null) {
+ return mAttachInfo.getViewRoot();
+ }
+ return null;
+ }
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 8198254958f4..5b695f4c425a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2053,26 +2053,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = childrenCount - 1; i >= 0; i--) {
final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
- View childWithAccessibilityFocus =
- event.isTargetAccessibilityFocus()
- ? findChildWithAccessibilityFocus()
- : null;
if (!child.canReceivePointerEvents()
|| !isTransformedTouchPointInView(x, y, child, null)) {
-
- // If there is a view that has accessibility focus we want it
- // to get the event first and if not handled we will perform a
- // normal dispatch. We may do a double iteration but this is
- // safer given the timeframe.
- if (childWithAccessibilityFocus != null) {
- if (childWithAccessibilityFocus != child) {
- continue;
- }
- childWithAccessibilityFocus = null;
- i = childrenCount - 1;
- }
- event.setTargetAccessibilityFocus(false);
continue;
}
final PointerIcon pointerIcon =
@@ -2730,8 +2713,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
childrenCount, i, customOrder);
final View child = getAndVerifyPreorderedView(
preorderedList, children, childIndex);
+
+ // If there is a view that has accessibility focus we want it
+ // to get the event first and if not handled we will perform a
+ // normal dispatch. We may do a double iteration but this is
+ // safer given the timeframe.
+ if (childWithAccessibilityFocus != null) {
+ if (childWithAccessibilityFocus != child) {
+ continue;
+ }
+ childWithAccessibilityFocus = null;
+ i = childrenCount - 1;
+ }
+
if (!child.canReceivePointerEvents()
|| !isTransformedTouchPointInView(x, y, child, null)) {
+ ev.setTargetAccessibilityFocus(false);
continue;
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
new file mode 100644
index 000000000000..3c755981a440
--- /dev/null
+++ b/core/java/android/view/ViewRoot.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.view;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UiThread;
+
+/**
+ * Provides an interface to the root-Surface of a View Hierarchy or Window. This
+ * is used in combination with the {@link android.view.SurfaceControl} API to enable
+ * attaching app created SurfaceControl to the ViewRoot's surface hierarchy, and enable
+ * SurfaceTransactions to be performed in sync with the ViewRoot drawing. This object
+ * is obtained from {@link android.view.View#getViewRoot} and
+ * {@link android.view.Window#getViewRoot}. It must be used from the UI thread of
+ * the object it was obtained from.
+ */
+@UiThread
+public interface ViewRoot {
+ /**
+ * Create a transaction which will reparent {@param child} to the ViewRoot. See
+ * {@link SurfaceControl.Transaction#reparent}. This transacton must be applied
+ * or merged in to another transaction by the caller, otherwise it will have
+ * no effect.
+ *
+ * @param child The SurfaceControl to reparent.
+ * @return A new transaction which performs the reparent operation when applied.
+ */
+ @Nullable SurfaceControl.Transaction buildReparentTransaction(@NonNull SurfaceControl child);
+
+ /**
+ * Consume the passed in transaction, and request the ViewRoot to apply it with the
+ * next draw. This transaction will be merged with the buffer transaction from the ViewRoot
+ * and they will show up on-screen atomically synced.
+ *
+ * This will not cause a draw to be scheduled, and if there are no other changes
+ * to the View hierarchy you may need to call {@link android.view.View#invalidate}
+ */
+ boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t);
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ded5fb4aabf0..54572285bd01 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -225,7 +225,7 @@ import java.util.concurrent.CountDownLatch;
*/
@SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
public final class ViewRootImpl implements ViewParent,
- View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
+ View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks, ViewRoot {
private static final String TAG = "ViewRootImpl";
private static final boolean DBG = false;
private static final boolean LOCAL_LOGV = false;
@@ -1195,8 +1195,7 @@ public final class ViewRootImpl implements ViewParent,
Looper.myLooper());
if (mAttachInfo.mThreadedRenderer != null) {
- InputMetricsListener listener =
- new InputMetricsListener(mInputEventReceiver);
+ InputMetricsListener listener = new InputMetricsListener();
mHardwareRendererObserver = new HardwareRendererObserver(
listener, listener.data, mHandler, true /*waitForPresentTime*/);
mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
@@ -1392,6 +1391,9 @@ public final class ViewRootImpl implements ViewParent,
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mHardwareAccelerated =
mAttachInfo.mHardwareAccelerationRequested = true;
+ if (mHardwareRendererObserver != null) {
+ mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
+ }
}
}
}
@@ -3209,7 +3211,9 @@ public final class ViewRootImpl implements ViewParent,
Log.d(mTag, "Relayout called with blastSync");
}
reportNextDraw();
- mNextDrawUseBlastSync = true;
+ if (isHardwareEnabled()) {
+ mNextDrawUseBlastSync = true;
+ }
}
boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
@@ -8083,6 +8087,9 @@ public final class ViewRootImpl implements ViewParent,
ThreadedRenderer hardwareRenderer = mAttachInfo.mThreadedRenderer;
if (hardwareRenderer != null) {
+ if (mHardwareRendererObserver != null) {
+ hardwareRenderer.removeObserver(mHardwareRendererObserver);
+ }
if (mView != null) {
hardwareRenderer.destroyHardwareResources(mView);
}
@@ -8584,18 +8591,12 @@ public final class ViewRootImpl implements ViewParent,
super.dispose();
}
}
- WindowInputEventReceiver mInputEventReceiver;
+ private WindowInputEventReceiver mInputEventReceiver;
final class InputMetricsListener
implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
public long[] data = new long[FrameMetrics.Index.FRAME_STATS_COUNT];
- private InputEventReceiver mReceiver;
-
- InputMetricsListener(InputEventReceiver receiver) {
- mReceiver = receiver;
- }
-
@Override
public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
final int inputEventId = (int) data[FrameMetrics.Index.INPUT_EVENT_ID];
@@ -8609,7 +8610,10 @@ public final class ViewRootImpl implements ViewParent,
return;
}
final long gpuCompletedTime = data[FrameMetrics.Index.GPU_COMPLETED];
- mReceiver.reportLatencyInfo(inputEventId, gpuCompletedTime, presentTime);
+ if (mInputEventReceiver == null) {
+ return;
+ }
+ mInputEventReceiver.reportTimeline(inputEventId, gpuCompletedTime, presentTime);
}
}
HardwareRendererObserver mHardwareRendererObserver;
@@ -10212,9 +10216,6 @@ public final class ViewRootImpl implements ViewParent,
if (useBLAST() && mBlastBufferQueue != null) {
mBlastBufferQueue.mergeWithNextTransaction(transaction, frameNumber);
- } else {
- transaction.deferTransactionUntil(surfaceControl, surfaceControl, frameNumber);
- transaction.apply();
}
}
@@ -10257,4 +10258,21 @@ public final class ViewRootImpl implements ViewParent,
t.apply();
}
}
+
+ @Override
+ @Nullable public SurfaceControl.Transaction buildReparentTransaction(
+ @NonNull SurfaceControl child) {
+ if (mSurfaceControl.isValid()) {
+ return new SurfaceControl.Transaction().reparent(child, mSurfaceControl);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t) {
+ registerRtFrameCallback(frame -> {
+ mergeWithNextTransaction(t, frame);
+ });
+ return true;
+ }
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 8b3fb2e9e751..e2466345ff4a 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -373,12 +373,12 @@ public abstract class ViewStructure {
public void setImportantForAutofill(@AutofillImportance int mode) {}
/**
- * Sets the MIME types accepted by this view. See {@link View#getOnReceiveContentMimeTypes()}.
+ * Sets the MIME types accepted by this view. See {@link View#getReceiveContentMimeTypes()}.
*
* <p>Should only be set when the node is used for Autofill or Content Capture purposes - it
* will be ignored when used for Assist.
*/
- public void setOnReceiveContentMimeTypes(
+ public void setReceiveContentMimeTypes(
@SuppressLint("NullableCollection") @Nullable String[] mimeTypes) {}
/**
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index c814e5add1b7..52a09701803d 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1703,29 +1703,31 @@ public abstract class Window {
public abstract void setBackgroundDrawable(Drawable drawable);
/**
+ * <p>
* Blurs the screen behind the window within the bounds of the window.
- *
+ * </p><p>
* The density of the blur is set by the blur radius. The radius defines the size
* of the neighbouring area, from which pixels will be averaged to form the final
* color for each pixel. The operation approximates a Gaussian blur.
* A radius of 0 means no blur. The higher the radius, the denser the blur.
- *
+ * </p><p>
* The window background drawable is drawn on top of the blurred region. The blur
* region bounds and rounded corners will mimic those of the background drawable.
- *
+ * </p><p>
* For the blur region to be visible, the window has to be translucent. See
* {@link android.R.styleable#Window_windowIsTranslucent}.
- *
+ * </p><p>
* Note the difference with {@link WindowManager.LayoutParams#setBlurBehindRadius},
* which blurs the whole screen behind the window. Background blur blurs the screen behind
* only within the bounds of the window.
- *
+ * </p><p>
* Some devices might not support cross-window blur due to GPU limitations. It can also be
* disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
* when minimal post processing is requested. In such situations, no blur will be computed or
* drawn, resulting in a transparent window background. To avoid this, the app might want to
* change its theme to one that does not use blurs. To listen for cross-window blur
* enabled/disabled events, use {@link WindowManager#addCrossWindowBlurEnabledListener}.
+ * </p>
*
* @param blurRadius The blur radius to use for window background blur in pixels
*
@@ -2717,4 +2719,14 @@ public abstract class Window {
public @Nullable WindowInsetsController getInsetsController() {
return null;
}
+
+ /**
+ * This will be null before a content view is added, e.g. via
+ * {@link #setContentView} or {@link #addContentView}.
+ *
+ * @return The {@link android.view.ViewRoot} interface for this Window
+ */
+ public @Nullable ViewRoot getViewRoot() {
+ return null;
+ }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 93c3cab5b787..4b56fd740e8d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -818,16 +818,18 @@ public interface WindowManager extends ViewManager {
}
/**
+ * <p>
* Returns whether cross-window blur is currently enabled. This affects both window blur behind
* (see {@link LayoutParams#setBlurBehindRadius}) and window background blur (see
* {@link Window#setBackgroundBlurRadius}).
- *
+ * </p><p>
* Cross-window blur might not be supported by some devices due to GPU limitations. It can also
* be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
* when minimal post processing is requested. In such situations, no blur will be computed or
* drawn, so the blur target area will not be blurred. To handle this, the app might want to
* change its theme to one that does not use blurs. To listen for cross-window blur
* enabled/disabled events, use {@link #addCrossWindowBlurEnabledListener}.
+ * </p>
*
* @see #addCrossWindowBlurEnabledListener
* @see LayoutParams#setBlurBehindRadius
@@ -838,21 +840,22 @@ public interface WindowManager extends ViewManager {
}
/**
+ * <p>
* Adds a listener, which will be called when cross-window blurs are enabled/disabled at
* runtime. This affects both window blur behind (see {@link LayoutParams#setBlurBehindRadius})
* and window background blur (see {@link Window#setBackgroundBlurRadius}).
- *
+ * </p><p>
* Cross-window blur might not be supported by some devices due to GPU limitations. It can also
* be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
* when minimal post processing is requested. In such situations, no blur will be computed or
* drawn, so the blur target area will not be blurred. To handle this, the app might want to
* change its theme to one that does not use blurs.
- *
+ * </p><p>
* The listener will be called on the main thread.
- *
+ * </p><p>
* If the listener is added successfully, it will be called immediately with the current
* cross-window blur enabled state.
- *
+ * </p>
*
* @param listener the listener to be added. It will be called back with a boolean parameter,
* which is true if cross-window blur is enabled and false if it is disabled
@@ -866,18 +869,20 @@ public interface WindowManager extends ViewManager {
}
/**
+ * <p>
* Adds a listener, which will be called when cross-window blurs are enabled/disabled at
* runtime. This affects both window blur behind (see {@link LayoutParams#setBlurBehindRadius})
* and window background blur (see {@link Window#setBackgroundBlurRadius}).
- *
+ * </p><p>
* Cross-window blur might not be supported by some devices due to GPU limitations. It can also
* be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
* when minimal post processing is requested. In such situations, no blur will be computed or
* drawn, so the blur target area will not be blurred. To handle this, the app might want to
* change its theme to one that does not use blurs.
- *
+ * </p><p>
* If the listener is added successfully, it will be called immediately with the current
* cross-window blur enabled state.
+ * </p>
*
* @param executor {@link Executor} to handle the listener callback
* @param listener the listener to be added. It will be called back with a boolean parameter,
@@ -3627,21 +3632,22 @@ public interface WindowManager extends ViewManager {
}
/**
+ * <p>
* Blurs the screen behind the window. The effect is similar to that of {@link #dimAmount},
* but instead of dimmed, the content behind the window will be blurred (or combined with
* the dim amount, if such is specified).
- *
+ * </p><p>
* The density of the blur is set by the blur radius. The radius defines the size
* of the neighbouring area, from which pixels will be averaged to form the final
* color for each pixel. The operation approximates a Gaussian blur.
* A radius of 0 means no blur. The higher the radius, the denser the blur.
- *
+ * </p><p>
* Note the difference with {@link android.view.Window#setBackgroundBlurRadius},
* which blurs only within the bounds of the window. Blur behind blurs the whole screen
* behind the window.
- *
+ * </p><p>
* Requires {@link #FLAG_BLUR_BEHIND} to be set.
- *
+ * </p><p>
* Cross-window blur might not be supported by some devices due to GPU limitations. It can
* also be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling
* is used or when minimal post processing is requested. In such situations, no blur will
@@ -3649,7 +3655,7 @@ public interface WindowManager extends ViewManager {
* and the content behind it. To avoid this, the app might want to use more
* {@link #dimAmount} on its window. To listen for cross-window blur enabled/disabled
* events, use {@link #addCrossWindowBlurEnabledListener}.
- *
+ * </p>
* @param blurBehindRadius The blur radius to use for blur behind in pixels
*
* @see #FLAG_BLUR_BEHIND
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 9ab2c2b8bcb1..d14dc6e71c00 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -158,6 +158,7 @@ public class AccessibilityCache {
* @param event An event.
*/
public void onAccessibilityEvent(AccessibilityEvent event) {
+ AccessibilityNodeInfo nodeToRefresh = null;
synchronized (mLock) {
if (DEBUG) {
Log.i(LOG_TAG, "onAccessibilityEvent(" + event + ")");
@@ -166,17 +167,19 @@ public class AccessibilityCache {
switch (eventType) {
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- refreshCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
+ removeCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
}
mAccessibilityFocus = event.getSourceNodeId();
mAccessibilityFocusedWindow = event.getWindowId();
- refreshCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
+ nodeToRefresh = removeCachedNodeLocked(mAccessibilityFocusedWindow,
+ mAccessibilityFocus);
} break;
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
if (mAccessibilityFocus == event.getSourceNodeId()
&& mAccessibilityFocusedWindow == event.getWindowId()) {
- refreshCachedNodeLocked(mAccessibilityFocusedWindow, mAccessibilityFocus);
+ nodeToRefresh = removeCachedNodeLocked(mAccessibilityFocusedWindow,
+ mAccessibilityFocus);
mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
@@ -184,17 +187,18 @@ public class AccessibilityCache {
case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
if (mInputFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- refreshCachedNodeLocked(event.getWindowId(), mInputFocus);
+ removeCachedNodeLocked(event.getWindowId(), mInputFocus);
}
mInputFocus = event.getSourceNodeId();
- refreshCachedNodeLocked(event.getWindowId(), mInputFocus);
+ nodeToRefresh = removeCachedNodeLocked(event.getWindowId(), mInputFocus);
} break;
case AccessibilityEvent.TYPE_VIEW_SELECTED:
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
case AccessibilityEvent.TYPE_VIEW_CLICKED:
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
- refreshCachedNodeLocked(event.getWindowId(), event.getSourceNodeId());
+ nodeToRefresh = removeCachedNodeLocked(event.getWindowId(),
+ event.getSourceNodeId());
} break;
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
@@ -205,7 +209,7 @@ public class AccessibilityCache {
& AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) != 0) {
clearSubTreeLocked(windowId, sourceId);
} else {
- refreshCachedNodeLocked(windowId, sourceId);
+ nodeToRefresh = removeCachedNodeLocked(windowId, sourceId);
}
}
} break;
@@ -218,8 +222,8 @@ public class AccessibilityCache {
if (event.getWindowChanges()
== AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) {
// Don't need to clear all cache. Unless the changes are related to
- // content, we won't clear all cache here.
- refreshCachedWindowLocked(event.getWindowId());
+ // content, we won't clear all cache here with clear().
+ clearWindowCacheLocked();
break;
}
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
@@ -228,59 +232,34 @@ public class AccessibilityCache {
}
}
+ if (nodeToRefresh != null) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Refreshing and re-adding cached node.");
+ }
+ if (mAccessibilityNodeRefresher.refreshNode(nodeToRefresh, true)) {
+ add(nodeToRefresh);
+ }
+ }
if (CHECK_INTEGRITY) {
checkIntegrity();
}
}
- private void refreshCachedNodeLocked(int windowId, long sourceId) {
+ private AccessibilityNodeInfo removeCachedNodeLocked(int windowId, long sourceId) {
if (DEBUG) {
- Log.i(LOG_TAG, "Refreshing cached node.");
+ Log.i(LOG_TAG, "Removing cached node.");
}
-
LongSparseArray<AccessibilityNodeInfo> nodes = mNodeCache.get(windowId);
if (nodes == null) {
- return;
+ return null;
}
AccessibilityNodeInfo cachedInfo = nodes.get(sourceId);
// If the source is not in the cache - nothing to do.
if (cachedInfo == null) {
- return;
- }
- // The node changed so we will just refresh it right now.
- if (mAccessibilityNodeRefresher.refreshNode(cachedInfo, true)) {
- return;
- }
- // Weird, we could not refresh. Just evict the entire sub-tree.
- clearSubTreeLocked(windowId, sourceId);
- }
-
- private void refreshCachedWindowLocked(int windowId) {
- if (DEBUG) {
- Log.i(LOG_TAG, "Refreshing cached window.");
- }
-
- if (windowId == AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
- return;
- }
-
- final int displayCounts = mWindowCacheByDisplay.size();
- for (int i = 0; i < displayCounts; i++) {
- final SparseArray<AccessibilityWindowInfo> windowsOfDisplay =
- mWindowCacheByDisplay.valueAt(i);
- if (windowsOfDisplay == null) {
- continue;
- }
- final AccessibilityWindowInfo window = windowsOfDisplay.get(windowId);
- if (window == null) {
- continue;
- }
- if (!mAccessibilityNodeRefresher.refreshWindow(window)) {
- // If we fail to refresh the window, clear all windows.
- clearWindowCacheLocked();
- }
- return;
+ return null;
}
+ nodes.remove(sourceId);
+ return cachedInfo;
}
/**
@@ -450,7 +429,7 @@ public class AccessibilityCache {
if (clone.isAccessibilityFocused()) {
if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
&& mAccessibilityFocus != sourceId) {
- refreshCachedNodeLocked(windowId, mAccessibilityFocus);
+ removeCachedNodeLocked(windowId, mAccessibilityFocus);
}
mAccessibilityFocus = sourceId;
mAccessibilityFocusedWindow = windowId;
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index f63749be6df2..e64157734fdb 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -20,6 +20,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -39,6 +40,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
@@ -83,6 +85,8 @@ public final class AccessibilityInteractionClient
public static final int NO_ID = -1;
+ public static final String CALL_STACK = "call_stack";
+
private static final String LOG_TAG = "AccessibilityInteractionClient";
private static final boolean DEBUG = false;
@@ -113,7 +117,10 @@ public final class AccessibilityInteractionClient
private final Object mInstanceLock = new Object();
+ private final AccessibilityManager mAccessibilityManager;
+
private volatile int mInteractionId = -1;
+ private volatile int mCallingUid = Process.INVALID_UID;
private AccessibilityNodeInfo mFindAccessibilityNodeInfoResult;
@@ -152,6 +159,37 @@ public final class AccessibilityInteractionClient
}
/**
+ * @return The client for the current thread.
+ */
+ public static AccessibilityInteractionClient getInstance(Context context) {
+ final long threadId = Thread.currentThread().getId();
+ if (context != null) {
+ return getInstanceForThread(threadId, context);
+ }
+ return getInstanceForThread(threadId);
+ }
+
+ /**
+ * <strong>Note:</strong> We keep one instance per interrogating thread since
+ * the instance contains state which can lead to undesired thread interleavings.
+ * We do not have a thread local variable since other threads should be able to
+ * look up the correct client knowing a thread id. See ViewRootImpl for details.
+ *
+ * @return The client for a given <code>threadId</code>.
+ */
+ public static AccessibilityInteractionClient getInstanceForThread(
+ long threadId, Context context) {
+ synchronized (sStaticLock) {
+ AccessibilityInteractionClient client = sClients.get(threadId);
+ if (client == null) {
+ client = new AccessibilityInteractionClient(context);
+ sClients.put(threadId, client);
+ }
+ return client;
+ }
+ }
+
+ /**
* Gets a cached accessibility service connection.
*
* @param connectionId The connection id.
@@ -197,6 +235,11 @@ public final class AccessibilityInteractionClient
private AccessibilityInteractionClient() {
/* reducing constructor visibility */
+ mAccessibilityManager = null;
+ }
+
+ private AccessibilityInteractionClient(Context context) {
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
}
/**
@@ -453,6 +496,15 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
+ if (mAccessibilityManager != null
+ && mAccessibilityManager.isAccessibilityTracingEnabled()) {
+ logTrace(connection, "findAccessibilityNodeInfoByAccessibilityId",
+ "InteractionId:" + interactionId + ";Result: " + infos
+ + ";connectionId=" + connectionId + ";accessibilityWindowId="
+ + accessibilityWindowId + ";accessibilityNodeId="
+ + accessibilityNodeId + ";bypassCache=" + bypassCache
+ + ";prefetchFlags=" + prefetchFlags + ";arguments=" + arguments);
+ }
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
bypassCache, packageNames);
if (infos != null && !infos.isEmpty()) {
@@ -514,6 +566,14 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
+ if (mAccessibilityManager != null
+ && mAccessibilityManager.isAccessibilityTracingEnabled()) {
+ logTrace(connection, "findAccessibilityNodeInfosByViewId", "InteractionId="
+ + interactionId + ":Result: " + infos + ";connectionId="
+ + connectionId + ";accessibilityWindowId=" + accessibilityWindowId
+ + ";accessibilityNodeId=" + accessibilityNodeId + ";viewId="
+ + viewId);
+ }
if (infos != null) {
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
false, packageNames);
@@ -568,6 +628,13 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
+ if (mAccessibilityManager != null
+ && mAccessibilityManager.isAccessibilityTracingEnabled()) {
+ logTrace(connection, "findAccessibilityNodeInfosByText", "InteractionId="
+ + interactionId + ":Result: " + infos + ";connectionId="
+ + connectionId + ";accessibilityWindowId=" + accessibilityWindowId
+ + ";accessibilityNodeId=" + accessibilityNodeId + ";text=" + text);
+ }
if (infos != null) {
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
false, packageNames);
@@ -621,6 +688,14 @@ public final class AccessibilityInteractionClient
if (packageNames != null) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
+ if (mAccessibilityManager != null
+ && mAccessibilityManager.isAccessibilityTracingEnabled()) {
+ logTrace(connection, "findFocus", "InteractionId=" + interactionId
+ + ":Result: " + info + ";connectionId=" + connectionId
+ + ";accessibilityWindowId=" + accessibilityWindowId
+ + ";accessibilityNodeId=" + accessibilityNodeId + ";focusType="
+ + focusType);
+ }
finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
return info;
}
@@ -671,6 +746,14 @@ public final class AccessibilityInteractionClient
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
+ if (mAccessibilityManager != null
+ && mAccessibilityManager.isAccessibilityTracingEnabled()) {
+ logTrace(connection, "focusSearch", "InteractionId=" + interactionId
+ + ":Result: " + info + ";connectionId=" + connectionId
+ + ";accessibilityWindowId=" + accessibilityWindowId
+ + ";accessibilityNodeId=" + accessibilityNodeId + ";direction="
+ + direction);
+ }
return info;
}
} else {
@@ -716,7 +799,17 @@ public final class AccessibilityInteractionClient
}
if (success) {
- return getPerformAccessibilityActionResultAndClear(interactionId);
+ final boolean result =
+ getPerformAccessibilityActionResultAndClear(interactionId);
+ if (mAccessibilityManager != null
+ && mAccessibilityManager.isAccessibilityTracingEnabled()) {
+ logTrace(connection, "performAccessibilityAction", "InteractionId="
+ + interactionId + ":Result: " + result + ";connectionId="
+ + connectionId + ";accessibilityWindowId=" + accessibilityWindowId
+ + ";accessibilityNodeId=" + accessibilityNodeId + ";action="
+ + action + ";arguments=" + arguments);
+ }
+ return result;
}
} else {
if (DEBUG) {
@@ -774,6 +867,7 @@ public final class AccessibilityInteractionClient
if (interactionId > mInteractionId) {
mFindAccessibilityNodeInfoResult = info;
mInteractionId = interactionId;
+ mCallingUid = Binder.getCallingUid();
}
mInstanceLock.notifyAll();
}
@@ -823,6 +917,7 @@ public final class AccessibilityInteractionClient
mFindAccessibilityNodeInfosResult = Collections.emptyList();
}
mInteractionId = interactionId;
+ mCallingUid = Binder.getCallingUid();
}
mInstanceLock.notifyAll();
}
@@ -851,6 +946,7 @@ public final class AccessibilityInteractionClient
if (interactionId > mInteractionId) {
mPerformAccessibilityActionResult = succeeded;
mInteractionId = interactionId;
+ mCallingUid = Binder.getCallingUid();
}
mInstanceLock.notifyAll();
}
@@ -1059,4 +1155,19 @@ public final class AccessibilityInteractionClient
}
return true;
}
+
+ private void logTrace(
+ IAccessibilityServiceConnection connection, String method, String params) {
+ try {
+ Bundle b = new Bundle();
+ ArrayList<StackTraceElement> callStack = new ArrayList<StackTraceElement>(
+ Arrays.asList(Thread.currentThread().getStackTrace()));
+ b.putSerializable(CALL_STACK, callStack);
+ connection.logTrace(SystemClock.elapsedRealtimeNanos(),
+ LOG_TAG + ".callback for " + method, params, Process.myPid(),
+ Thread.currentThread().getId(), mCallingUid, b);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Failed to log trace. " + e);
+ }
+ }
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 56dcd5951e5e..fc9e5e2ef04e 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -111,6 +111,9 @@ public final class AccessibilityManager {
public static final int STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000010;
/** @hide */
+ public static final int STATE_FLAG_ACCESSIBILITY_TRACING_ENABLED = 0x00000020;
+
+ /** @hide */
public static final int DALTONIZER_DISABLED = -1;
/** @hide */
@@ -232,6 +235,9 @@ public final class AccessibilityManager {
@UnsupportedAppUsage(trackingBug = 123768939L)
boolean mIsHighTextContrastEnabled;
+ // Whether accessibility tracing is enabled or not
+ boolean mIsAccessibilityTracingEnabled = false;
+
AccessibilityPolicy mAccessibilityPolicy;
private int mPerformingAction = 0;
@@ -1004,6 +1010,17 @@ public final class AccessibilityManager {
}
/**
+ * Gets accessibility tracing enabled state.
+ *
+ * @hide
+ */
+ public boolean isAccessibilityTracingEnabled() {
+ synchronized (mLock) {
+ return mIsAccessibilityTracingEnabled;
+ }
+ }
+
+ /**
* Get the preparers that are registered for an accessibility ID
*
* @param id The ID of interest
@@ -1197,6 +1214,8 @@ public final class AccessibilityManager {
(stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
final boolean highTextContrastEnabled =
(stateFlags & STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED) != 0;
+ final boolean accessibilityTracingEnabled =
+ (stateFlags & STATE_FLAG_ACCESSIBILITY_TRACING_ENABLED) != 0;
final boolean wasEnabled = isEnabled();
final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled;
@@ -1218,6 +1237,8 @@ public final class AccessibilityManager {
if (wasHighTextContrastEnabled != highTextContrastEnabled) {
notifyHighTextContrastStateChanged();
}
+
+ updateAccessibilityTracingState(accessibilityTracingEnabled);
}
/**
@@ -1675,6 +1696,15 @@ public final class AccessibilityManager {
}
/**
+ * Update mIsAccessibilityTracingEnabled.
+ */
+ private void updateAccessibilityTracingState(boolean enabled) {
+ synchronized (mLock) {
+ mIsAccessibilityTracingEnabled = enabled;
+ }
+ }
+
+ /**
* Update interactive and non-interactive UI timeout.
*
* @param uiTimeout A pair of {@code int}s. First integer for interactive one, and second
diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
index 4e9c229e03a0..c882c6e3200d 100644
--- a/core/java/android/view/contentcapture/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -114,7 +114,7 @@ public final class ViewNode extends AssistStructure.ViewNode {
private String[] mAutofillHints;
private AutofillValue mAutofillValue;
private CharSequence[] mAutofillOptions;
- private String[] mOnReceiveContentMimeTypes;
+ private String[] mReceiveContentMimeTypes;
/** @hide */
public ViewNode() {
@@ -172,7 +172,7 @@ public final class ViewNode extends AssistStructure.ViewNode {
mLocaleList = parcel.readParcelable(null);
}
if ((nodeFlags & FLAGS_HAS_MIME_TYPES) != 0) {
- mOnReceiveContentMimeTypes = parcel.readStringArray();
+ mReceiveContentMimeTypes = parcel.readStringArray();
}
if ((nodeFlags & FLAGS_HAS_INPUT_TYPE) != 0) {
mInputType = parcel.readInt();
@@ -470,8 +470,8 @@ public final class ViewNode extends AssistStructure.ViewNode {
@Override
@Nullable
- public String[] getOnReceiveContentMimeTypes() {
- return mOnReceiveContentMimeTypes;
+ public String[] getReceiveContentMimeTypes() {
+ return mReceiveContentMimeTypes;
}
@Nullable
@@ -519,7 +519,7 @@ public final class ViewNode extends AssistStructure.ViewNode {
if (mLocaleList != null) {
nodeFlags |= FLAGS_HAS_LOCALE_LIST;
}
- if (mOnReceiveContentMimeTypes != null) {
+ if (mReceiveContentMimeTypes != null) {
nodeFlags |= FLAGS_HAS_MIME_TYPES;
}
if (mInputType != 0) {
@@ -599,7 +599,7 @@ public final class ViewNode extends AssistStructure.ViewNode {
parcel.writeParcelable(mLocaleList, 0);
}
if ((nodeFlags & FLAGS_HAS_MIME_TYPES) != 0) {
- parcel.writeStringArray(mOnReceiveContentMimeTypes);
+ parcel.writeStringArray(mReceiveContentMimeTypes);
}
if ((nodeFlags & FLAGS_HAS_INPUT_TYPE) != 0) {
parcel.writeInt(mInputType);
@@ -929,8 +929,8 @@ public final class ViewNode extends AssistStructure.ViewNode {
}
@Override
- public void setOnReceiveContentMimeTypes(@Nullable String[] mimeTypes) {
- mNode.mOnReceiveContentMimeTypes = mimeTypes;
+ public void setReceiveContentMimeTypes(@Nullable String[] mimeTypes) {
+ mNode.mReceiveContentMimeTypes = mimeTypes;
}
@Override
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 9f796c068abe..bdd12063e6cf 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -938,12 +938,12 @@ public class BaseInputConnection implements InputConnection {
/**
* Default implementation which invokes {@link View#performReceiveContent} on the target
- * view if the view {@link View#getOnReceiveContentMimeTypes allows} content insertion;
+ * view if the view {@link View#getReceiveContentMimeTypes allows} content insertion;
* otherwise returns false without any side effects.
*/
public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
ClipDescription description = inputContentInfo.getDescription();
- if (mTargetView.getOnReceiveContentMimeTypes() == null) {
+ if (mTargetView.getReceiveContentMimeTypes() == null) {
if (DEBUG) {
Log.d(TAG, "Can't insert content from IME: content=" + description);
}
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index bde4cb7c4fc3..4a52b1f01b46 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -725,7 +725,8 @@ public class EditorInfo implements InputType, Parcelable {
* protocol.
*/
@Nullable
- public CharSequence getInitialTextBeforeCursor(int length, int flags) {
+ public CharSequence getInitialTextBeforeCursor(
+ @IntRange(from = 0) int length, @InputConnection.GetTextType int flags) {
if (mInitialSurroundingText == null) {
return null;
}
@@ -750,7 +751,7 @@ public class EditorInfo implements InputType, Parcelable {
* this protocol is not supported.
*/
@Nullable
- public CharSequence getInitialSelectedText(int flags) {
+ public CharSequence getInitialSelectedText(@InputConnection.GetTextType int flags) {
if (mInitialSurroundingText == null) {
return null;
}
@@ -792,7 +793,8 @@ public class EditorInfo implements InputType, Parcelable {
* protocol.
*/
@Nullable
- public CharSequence getInitialTextAfterCursor(int length, int flags) {
+ public CharSequence getInitialTextAfterCursor(
+ @IntRange(from = 0) int length, @InputConnection.GetTextType int flags) {
if (mInitialSurroundingText == null) {
return null;
}
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index de4554b9e624..d2db0df6c597 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -101,11 +101,12 @@ public interface InputMethod {
* @param privilegedOperations IPC endpoint to do some privileged
* operations that are allowed only to the
* current IME.
+ * @param configChanges {@link InputMethodInfo#getConfigChanges()} declared by IME.
* @hide
*/
@MainThread
default void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations) {
+ IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
updateInputMethodDisplay(displayId);
attachToken(token);
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 6ba3b37ce214..c26b302db983 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -18,19 +18,23 @@ package android.view.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
+import android.inputmethodservice.InputMethodService;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -62,6 +66,7 @@ import java.util.List;
* @attr ref android.R.styleable#InputMethod_supportsInlineSuggestions
* @attr ref android.R.styleable#InputMethod_suppressesSpellChecker
* @attr ref android.R.styleable#InputMethod_showInInputMethodPicker
+ * @attr ref android.R.styleable#InputMethod_configChanges
*/
public final class InputMethodInfo implements Parcelable {
static final String TAG = "InputMethodInfo";
@@ -130,6 +135,12 @@ public final class InputMethodInfo implements Parcelable {
private final boolean mShowInInputMethodPicker;
/**
+ * The flag for configurations IME assumes the responsibility for handling in
+ * {@link InputMethodService#onConfigurationChanged(Configuration)}}.
+ */
+ private final int mHandledConfigChanges;
+
+ /**
* @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
* @return a unique ID to be returned by {@link #getId()}. We have used
* {@link ComponentName#flattenToShortString()} for this purpose (and it is already
@@ -221,6 +232,8 @@ public final class InputMethodInfo implements Parcelable {
com.android.internal.R.styleable.InputMethod_suppressesSpellChecker, false);
showInInputMethodPicker = sa.getBoolean(
com.android.internal.R.styleable.InputMethod_showInInputMethodPicker, true);
+ mHandledConfigChanges = sa.getInt(
+ com.android.internal.R.styleable.InputMethod_configChanges, 0);
sa.recycle();
final int depth = parser.getDepth();
@@ -309,6 +322,7 @@ public final class InputMethodInfo implements Parcelable {
mIsVrOnly = source.readBoolean();
mService = ResolveInfo.CREATOR.createFromParcel(source);
mSubtypes = new InputMethodSubtypeArray(source);
+ mHandledConfigChanges = source.readInt();
mForceDefault = false;
}
@@ -320,7 +334,22 @@ public final class InputMethodInfo implements Parcelable {
this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
- false /* inlineSuggestionsEnabled */, false /* isVrOnly */);
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
+ 0 /* handledConfigChanges */);
+ }
+
+ /**
+ * Temporary API for creating a built-in input method for test.
+ * @hide
+ */
+ @TestApi
+ public InputMethodInfo(@NonNull String packageName, @NonNull String className,
+ @NonNull CharSequence label, @NonNull String settingsActivity,
+ int handledConfigChanges) {
+ this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
+ settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
+ false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */, handledConfigChanges);
}
/**
@@ -332,7 +361,7 @@ public final class InputMethodInfo implements Parcelable {
boolean forceDefault) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
- false /* isVrOnly */);
+ false /* isVrOnly */, 0 /* handledconfigChanges */);
}
/**
@@ -343,7 +372,8 @@ public final class InputMethodInfo implements Parcelable {
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
- supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly);
+ supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
+ 0 /* handledConfigChanges */);
}
/**
@@ -353,7 +383,7 @@ public final class InputMethodInfo implements Parcelable {
public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
- boolean isVrOnly) {
+ boolean isVrOnly, int handledConfigChanges) {
final ServiceInfo si = ri.serviceInfo;
mService = ri;
mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -367,6 +397,7 @@ public final class InputMethodInfo implements Parcelable {
mSuppressesSpellChecker = false;
mShowInInputMethodPicker = true;
mIsVrOnly = isVrOnly;
+ mHandledConfigChanges = handledConfigChanges;
}
private static ResolveInfo buildFakeResolveInfo(String packageName, String className,
@@ -513,6 +544,17 @@ public final class InputMethodInfo implements Parcelable {
}
}
+ /**
+ * Returns the bit mask of kinds of configuration changes that this IME
+ * can handle itself (without being restarted by the system).
+ *
+ * @attr ref android.R.styleable#InputMethod_configChanges
+ */
+ @ActivityInfo.Config
+ public int getConfigChanges() {
+ return mHandledConfigChanges;
+ }
+
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
@@ -622,6 +664,7 @@ public final class InputMethodInfo implements Parcelable {
dest.writeBoolean(mIsVrOnly);
mService.writeToParcel(dest, flags);
mSubtypes.writeToParcel(dest);
+ dest.writeInt(mHandledConfigChanges);
}
/**
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index 0fa6e16b2e03..53e354f8200e 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -30,6 +30,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.util.ArrayMap;
+import android.util.IntArray;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -100,7 +101,8 @@ public class UiTranslationController {
*/
public void updateUiTranslationState(@UiTranslationState int state, TranslationSpec sourceSpec,
TranslationSpec destSpec, List<AutofillId> views) {
- if (!mActivity.isResumed()) {
+ if (!mActivity.isResumed() && (state == STATE_UI_TRANSLATION_STARTED
+ || state == STATE_UI_TRANSLATION_RESUMED)) {
return;
}
Log.i(TAG, "updateUiTranslationState state: " + stateToString(state)
@@ -241,13 +243,11 @@ public class UiTranslationController {
final SparseArray<ViewTranslationResponse> viewsResult = new SparseArray<>();
final SparseArray<LongSparseArray<ViewTranslationResponse>> virtualViewsResult =
new SparseArray<>();
- // TODO: use another structure to prevent autoboxing?
- final List<Integer> viewIds = new ArrayList<>();
-
+ final IntArray viewIds = new IntArray(1);
for (int i = 0; i < translatedResult.size(); i++) {
final ViewTranslationResponse result = translatedResult.valueAt(i);
final AutofillId autofillId = result.getAutofillId();
- if (!viewIds.contains(autofillId.getViewId())) {
+ if (viewIds.indexOf(autofillId.getViewId()) < 0) {
viewIds.add(autofillId.getViewId());
}
if (autofillId.isNonVirtual()) {
@@ -405,23 +405,29 @@ public class UiTranslationController {
// Filter the request views's AutofillId
SparseIntArray virtualViewChildCount = getRequestVirtualViewChildCount(views);
Map<AutofillId, long[]> viewIds = new ArrayMap<>();
+ Map<AutofillId, Integer> unusedIndices = null;
for (int i = 0; i < views.size(); i++) {
AutofillId autofillId = views.get(i);
if (autofillId.isNonVirtual()) {
viewIds.put(autofillId, null);
} else {
+ if (unusedIndices == null) {
+ unusedIndices = new ArrayMap<>();
+ }
// The virtual id get from content capture is long, see getVirtualChildLongId()
// e.g. 1001, 1001:2, 1002:1 -> 1001, <1,2>; 1002, <1>
AutofillId virtualViewAutofillId = new AutofillId(autofillId.getViewId());
long[] childs;
+ int end = 0;
if (viewIds.containsKey(virtualViewAutofillId)) {
childs = viewIds.get(virtualViewAutofillId);
+ end = unusedIndices.get(virtualViewAutofillId);
} else {
int childCount = virtualViewChildCount.get(autofillId.getViewId());
childs = new long[childCount];
viewIds.put(virtualViewAutofillId, childs);
}
- int end = childs.length - 1;
+ unusedIndices.put(virtualViewAutofillId, end + 1);
childs[end] = autofillId.getVirtualChildLongId();
}
}
@@ -465,7 +471,7 @@ public class UiTranslationController {
return new int[] {TranslationSpec.DATA_FORMAT_TEXT};
}
- private void findViewsTraversalByAutofillIds(List<Integer> sourceViewIds) {
+ private void findViewsTraversalByAutofillIds(IntArray sourceViewIds) {
final ArrayList<ViewRootImpl> roots =
WindowManagerGlobal.getInstance().getRootViews(mActivity.getActivityToken());
for (int rootNum = 0; rootNum < roots.size(); rootNum++) {
@@ -479,7 +485,7 @@ public class UiTranslationController {
}
private void findViewsTraversalByAutofillIds(ViewGroup viewGroup,
- List<Integer> sourceViewIds) {
+ IntArray sourceViewIds) {
final int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; ++i) {
final View child = viewGroup.getChildAt(i);
@@ -491,9 +497,10 @@ public class UiTranslationController {
}
}
- private void addViewIfNeeded(List<Integer> sourceViewIds, View view) {
+ private void addViewIfNeeded(IntArray sourceViewIds, View view) {
final AutofillId autofillId = view.getAutofillId();
- if (sourceViewIds.contains(autofillId.getViewId()) && !mViews.containsKey(autofillId)) {
+ if ((sourceViewIds.indexOf(autofillId.getViewId()) >= 0)
+ && !mViews.containsKey(autofillId)) {
mViews.put(autofillId, new WeakReference<>(view));
}
}
diff --git a/core/java/android/view/translation/ViewTranslationRequest.java b/core/java/android/view/translation/ViewTranslationRequest.java
index 180b1c2c166a..4d8fb99023c9 100644
--- a/core/java/android/view/translation/ViewTranslationRequest.java
+++ b/core/java/android/view/translation/ViewTranslationRequest.java
@@ -35,7 +35,8 @@ import java.util.Set;
* Wrapper class representing a translation request associated with a {@link android.view.View} to
* be used by {@link android.service.translation.TranslationService}.
*/
-@DataClass(genBuilder = true, genToString = true, genEqualsHashCode = true, genGetters = false)
+@DataClass(genBuilder = false, genToString = true, genEqualsHashCode = true, genGetters = false,
+ genHiddenConstructor = true)
public final class ViewTranslationRequest implements Parcelable {
/**
@@ -91,10 +92,39 @@ public final class ViewTranslationRequest implements Parcelable {
return Collections.emptyMap();
}
- @DataClass.Suppress({"addTranslationRequestValue", "setAutofillId"})
- abstract static class BaseBuilder {
+ /**
+ * A builder for building ViewTranslationRequest.
+ */
+ public static final class Builder {
+
+ private @NonNull AutofillId mAutofillId;
+ private @NonNull Map<String, TranslationRequestValue> mTranslationRequestValues;
+
+ private long mBuilderFieldsSet = 0L;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param autofillId The {@link AutofillId} of the view associated with this request.
+ */
+ public Builder(@NonNull AutofillId autofillId) {
+ mAutofillId = autofillId;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAutofillId);
+ }
- abstract Builder setTranslationRequestValues(Map<String, TranslationRequestValue> value);
+ /**
+ * Creates a new Builder.
+ *
+ * @param autofillId the {@link AutofillId} of the non-virtual view hosting the virtual view
+ * hierarchy associated with this request.
+ * @param virtualChildId the id of the virtual child, relative to the parent.
+ */
+ public Builder(@NonNull AutofillId autofillId, long virtualChildId) {
+ mAutofillId = new AutofillId(autofillId, virtualChildId, AutofillId.NO_SESSION);
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAutofillId);
+ }
/**
* Sets the corresponding {@link TranslationRequestValue} for the provided key.
@@ -104,20 +134,50 @@ public final class ViewTranslationRequest implements Parcelable {
* @return this builder.
*/
@SuppressLint("MissingGetterMatchingBuilder")
- public Builder setValue(String key,
- TranslationRequestValue value) {
- final Builder builder = (Builder) this;
- if (builder.mTranslationRequestValues == null) {
+ @NonNull
+ public Builder setValue(@NonNull String key, @NonNull TranslationRequestValue value) {
+ if (mTranslationRequestValues == null) {
setTranslationRequestValues(new ArrayMap<>());
}
- builder.mTranslationRequestValues.put(key, value);
- return builder;
+ mTranslationRequestValues.put(key, value);
+ return this;
+ }
+
+ /**
+ * Builds the instance. This builder should not be touched after calling this!
+ */
+ @NonNull
+ public ViewTranslationRequest build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mTranslationRequestValues = defaultTranslationRequestValues();
+ }
+ ViewTranslationRequest o = new ViewTranslationRequest(
+ mAutofillId,
+ mTranslationRequestValues);
+ return o;
+ }
+
+ Builder setTranslationRequestValues(@NonNull Map<String, TranslationRequestValue> value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mTranslationRequestValues = value;
+ return this;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x4) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
}
}
- // Code below generated by codegen v1.0.22.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -130,8 +190,15 @@ public final class ViewTranslationRequest implements Parcelable {
//@formatter:off
+ /**
+ * Creates a new ViewTranslationRequest.
+ *
+ * @param autofillId
+ * The {@link AutofillId} of the view associated with this request.
+ * @hide
+ */
@DataClass.Generated.Member
- /* package-private */ ViewTranslationRequest(
+ public ViewTranslationRequest(
@NonNull AutofillId autofillId,
@NonNull Map<String,TranslationRequestValue> translationRequestValues) {
this.mAutofillId = autofillId;
@@ -234,67 +301,11 @@ public final class ViewTranslationRequest implements Parcelable {
}
};
- /**
- * A builder for {@link ViewTranslationRequest}
- */
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
- public static final class Builder extends BaseBuilder {
-
- private @NonNull AutofillId mAutofillId;
- private @NonNull Map<String,TranslationRequestValue> mTranslationRequestValues;
-
- private long mBuilderFieldsSet = 0L;
-
- /**
- * Creates a new Builder.
- *
- * @param autofillId
- * The {@link AutofillId} of the view associated with this request.
- */
- public Builder(
- @NonNull AutofillId autofillId) {
- mAutofillId = autofillId;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAutofillId);
- }
-
- @DataClass.Generated.Member
- @Override
- @NonNull Builder setTranslationRequestValues(@NonNull Map<String,TranslationRequestValue> value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mTranslationRequestValues = value;
- return this;
- }
-
- /** Builds the instance. This builder should not be touched after calling this! */
- public @NonNull ViewTranslationRequest build() {
- checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
-
- if ((mBuilderFieldsSet & 0x2) == 0) {
- mTranslationRequestValues = defaultTranslationRequestValues();
- }
- ViewTranslationRequest o = new ViewTranslationRequest(
- mAutofillId,
- mTranslationRequestValues);
- return o;
- }
-
- private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
- }
- }
- }
-
@DataClass.Generated(
- time = 1614992269658L,
- codegenVersion = "1.0.22",
+ time = 1617119791798L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/translation/ViewTranslationRequest.java",
- inputSignatures = "public static final java.lang.String ID_TEXT\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\npublic @android.annotation.NonNull android.view.translation.TranslationRequestValue getValue(java.lang.String)\npublic @android.annotation.NonNull java.util.Set<java.lang.String> getKeys()\npublic @android.annotation.NonNull android.view.autofill.AutofillId getAutofillId()\nprivate static java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nclass ViewTranslationRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\npublic @android.annotation.SuppressLint android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true, genGetters=false)\nabstract android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\npublic @android.annotation.SuppressLint android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final java.lang.String ID_TEXT\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\npublic @android.annotation.NonNull android.view.translation.TranslationRequestValue getValue(java.lang.String)\npublic @android.annotation.NonNull java.util.Set<java.lang.String> getKeys()\npublic @android.annotation.NonNull android.view.autofill.AutofillId getAutofillId()\nprivate static java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nclass ViewTranslationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate @android.annotation.NonNull java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate long mBuilderFieldsSet\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.view.translation.ViewTranslationRequest.Builder setValue(java.lang.String,android.view.translation.TranslationRequestValue)\npublic @android.annotation.NonNull android.view.translation.ViewTranslationRequest build()\n android.view.translation.ViewTranslationRequest.Builder setTranslationRequestValues(java.util.Map<java.lang.String,android.view.translation.TranslationRequestValue>)\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=false, genToString=true, genEqualsHashCode=true, genGetters=false, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 264736008782..770a1568241c 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -365,7 +365,6 @@ public interface WebViewProvider {
}
@SuppressLint("NullableCollection")
- @Nullable
default void onCreateTranslationRequests(
@NonNull @SuppressWarnings("unused") long[] virtualChildIds,
@NonNull @SuppressWarnings("unused") @DataFormat int[] supportedFormats,
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index c31462581c9f..2ac0342b80d3 100755
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4825,6 +4825,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
mTouchMode = TOUCH_MODE_FLING;
mSuppressIdleStateChangeCall = false;
+ removeCallbacks(this);
postOnAnimation(this);
if (PROFILE_FLINGING) {
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 1951194816bd..ae426d2c897f 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -626,20 +626,31 @@ public class EdgeEffect {
// assume rotations of increments of 90 degrees
float x = mTmpPoints[10] - mTmpPoints[8];
float width = right - left;
- float vecX = dampStretchVector(Math.max(-1f, Math.min(1f, x / width)));
+ float vecX = 0f;
+ if (width > 0) {
+ vecX = dampStretchVector(Math.max(-1f, Math.min(1f, x / width)));
+ }
+
float y = mTmpPoints[11] - mTmpPoints[9];
float height = bottom - top;
- float vecY = dampStretchVector(Math.max(-1f, Math.min(1f, y / height)));
- renderNode.stretch(
- left,
- top,
- right,
- bottom,
- vecX,
- vecY,
- mWidth,
- mHeight
- );
+ float vecY = 0f;
+ if (height > 0) {
+ vecY = dampStretchVector(Math.max(-1f, Math.min(1f, y / height)));
+ }
+
+ boolean hasStretchVectors = Float.compare(vecX, 0) != 0 || Float.compare(vecY, 0) != 0;
+ if (right > left && bottom > top && mWidth > 0 && mHeight > 0 && hasStretchVectors) {
+ renderNode.stretch(
+ left,
+ top,
+ right,
+ bottom,
+ vecX,
+ vecY,
+ mWidth,
+ mHeight
+ );
+ }
} else {
// This is TYPE_STRETCH and drawing into a Canvas that isn't a Recording Canvas,
// so no effect can be shown. Just end the effect.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ffaa31552a6a..40c79cf086fc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8773,7 +8773,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
outAttrs.initialSelEnd = getSelectionEnd();
outAttrs.initialCapsMode = ic.getCursorCapsMode(getInputType());
outAttrs.setInitialSurroundingText(mText);
- outAttrs.contentMimeTypes = getOnReceiveContentMimeTypes();
+ outAttrs.contentMimeTypes = getReceiveContentMimeTypes();
return ic;
}
}
@@ -11741,10 +11741,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
}
- String[] mimeTypes = getOnReceiveContentMimeTypes();
+ String[] mimeTypes = getReceiveContentMimeTypes();
if (mimeTypes == null && mEditor != null) {
// If the app hasn't set a listener for receiving content on this view (ie,
- // getOnReceiveContentMimeTypes() returns null), check if it implements the
+ // getReceiveContentMimeTypes() returns null), check if it implements the
// keyboard image API and, if possible, use those MIME types as fallback.
// This fallback is only in place for autofill, not other mechanisms for
// inserting content. See AUTOFILL_NON_TEXT_REQUIRES_ON_RECEIVE_CONTENT_LISTENER
@@ -11752,7 +11752,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mimeTypes = mEditor.getDefaultOnReceiveContentListener()
.getFallbackMimeTypesForAutofill(this);
}
- structure.setOnReceiveContentMimeTypes(mimeTypes);
+ structure.setReceiveContentMimeTypes(mimeTypes);
}
if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
diff --git a/core/java/android/widget/TextViewOnReceiveContentListener.java b/core/java/android/widget/TextViewOnReceiveContentListener.java
index 91fac5511807..0d5bf71dc955 100644
--- a/core/java/android/widget/TextViewOnReceiveContentListener.java
+++ b/core/java/android/widget/TextViewOnReceiveContentListener.java
@@ -194,7 +194,7 @@ public final class TextViewOnReceiveContentListener implements OnReceiveContentL
* non-text content.
*/
private static boolean isUsageOfImeCommitContentEnabled(@NonNull View view) {
- if (view.getOnReceiveContentMimeTypes() != null) {
+ if (view.getReceiveContentMimeTypes() != null) {
if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
Log.v(LOG_TAG, "Fallback to commitContent disabled (custom callback is set)");
}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 01bb199a1a6a..8a6856e3b51b 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -36,9 +36,9 @@ interface IAppOpsService {
// be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
// and not be reordered
int checkOperation(int code, int uid, String packageName);
- int noteOperation(int code, int uid, String packageName, @nullable String attributionTag,
+ SyncNotedAppOp noteOperation(int code, int uid, String packageName, @nullable String attributionTag,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
- int startOperation(IBinder clientId, int code, int uid, String packageName,
+ SyncNotedAppOp startOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String attributionTag, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
@UnsupportedAppUsage
@@ -53,10 +53,10 @@ interface IAppOpsService {
// End of methods also called by native code.
// Any new method exposed to native must be added after the last one, do not reorder
- int noteProxyOperation(int code, in AttributionSource attributionSource,
+ SyncNotedAppOp noteProxyOperation(int code, in AttributionSource attributionSource,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation);
- int startProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource,
+ SyncNotedAppOp startProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
boolean shouldCollectMessage, boolean skipProxyOperation);
void finishProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 957e416986e0..6bf46457a1de 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -34,7 +34,7 @@ import android.telephony.SignalStrength;
interface IBatteryStats {
// These first methods are also called by native code, so must
- // be kept in sync with frameworks/native/libs/binder/include/binder/IBatteryStats.h
+ // be kept in sync with frameworks/native/libs/binder/include_batterystats/batterystats/IBatteryStats.h
void noteStartSensor(int uid, int sensor);
void noteStopSensor(int uid, int sensor);
void noteStartVideo(int uid);
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index e4dd7b0629b5..20e520efc761 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -29,7 +29,7 @@ import com.android.internal.inputmethod.IVoidResultCallback;
* Actual operations are implemented and handled by InputMethodManagerService.
*/
oneway interface IInputMethodPrivilegedOperations {
- void setImeWindowStatus(int vis, int backDisposition, in IVoidResultCallback resultCallback);
+ void setImeWindowStatusAsync(int vis, int backDisposition);
void reportStartInput(in IBinder startInputToken, in IVoidResultCallback resultCallback);
void createInputContentUriToken(in Uri contentUri, in String packageName,
in IIInputContentUriTokenResultCallback resultCallback);
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 04cf3f3e546f..98c75b9ef428 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -95,8 +95,7 @@ public final class InputMethodPrivilegedOperations {
}
/**
- * Calls {@link IInputMethodPrivilegedOperations#setImeWindowStatus(int, int,
- * IVoidResultCallback)}.
+ * Calls {@link IInputMethodPrivilegedOperations#setImeWindowStatusAsync(int, int}.
*
* @param vis visibility flags
* @param backDisposition disposition flags
@@ -107,15 +106,13 @@ public final class InputMethodPrivilegedOperations {
* @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_ADJUST_NOTHING
*/
@AnyThread
- public void setImeWindowStatus(int vis, int backDisposition) {
+ public void setImeWindowStatusAsync(int vis, int backDisposition) {
final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
if (ops == null) {
return;
}
try {
- final Completable.Void value = Completable.createVoid();
- ops.setImeWindowStatus(vis, backDisposition, ResultCallbacks.of(value));
- Completable.getResult(value);
+ ops.setImeWindowStatusAsync(vis, backDisposition);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 7f0178e29d85..594a1a72ffcf 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -26,7 +26,9 @@ import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING;
import static com.android.internal.jank.InteractionJankMonitor.ACTION_METRICS_LOGGED;
import static com.android.internal.jank.InteractionJankMonitor.ACTION_SESSION_BEGIN;
+import static com.android.internal.jank.InteractionJankMonitor.ACTION_SESSION_CANCEL;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.HardwareRendererObserver;
@@ -45,6 +47,9 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor.Session;
import com.android.internal.util.FrameworkStatsLog;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A class that allows the app to get the frame metrics from HardwareRendererObserver.
* @hide
@@ -57,6 +62,26 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
private static final long INVALID_ID = -1;
public static final int NANOS_IN_MILLISECOND = 1_000_000;
+ static final int REASON_END_UNKNOWN = -1;
+ static final int REASON_END_NORMAL = 0;
+ static final int REASON_END_SURFACE_DESTROYED = 1;
+ static final int REASON_CANCEL_NORMAL = 16;
+ static final int REASON_CANCEL_NOT_BEGUN = 17;
+ static final int REASON_CANCEL_SAME_VSYNC = 18;
+
+ /** @hide */
+ @IntDef({
+ REASON_END_UNKNOWN,
+ REASON_END_NORMAL,
+ REASON_END_SURFACE_DESTROYED,
+ REASON_CANCEL_NORMAL,
+ REASON_CANCEL_NOT_BEGUN,
+ REASON_CANCEL_SAME_VSYNC,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Reasons {
+ }
+
private final HardwareRendererObserver mObserver;
private SurfaceControl mSurfaceControl;
private final int mTraceThresholdMissedFrames;
@@ -156,7 +181,14 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
// force finish the session.
mHandler.postDelayed(() -> {
synchronized (FrameTracker.this) {
+ if (DEBUG) {
+ Log.d(TAG, "surfaceDestroyed: " + mSession.getName()
+ + ", finalized=" + mMetricsFinalized
+ + ", info=" + mJankInfos.size()
+ + ", vsync=" + mBeginVsyncId + "-" + mEndVsyncId);
+ }
if (!mMetricsFinalized) {
+ end(REASON_END_SURFACE_DESTROYED);
finish(mJankInfos.size() - 1);
}
}
@@ -176,6 +208,9 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
mSession.setTimeStamp(System.nanoTime());
Trace.beginAsyncSection(mSession.getName(), (int) mBeginVsyncId);
mRendererWrapper.addObserver(mObserver);
+ if (DEBUG) {
+ Log.d(TAG, "begin: " + mSession.getName() + ", begin=" + mBeginVsyncId);
+ }
if (mSurfaceControl != null) {
mSurfaceControlWrapper.addJankStatsListener(this, mSurfaceControl);
}
@@ -187,15 +222,25 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
/**
* End the trace session of the CUJ.
*/
- public synchronized void end() {
+ public synchronized void end(@Reasons int reason) {
+ if (mEndVsyncId != INVALID_ID) return;
mEndVsyncId = mChoreographer.getVsyncId();
+
// Cancel the session if:
// 1. The session begins and ends at the same vsync id.
// 2. The session never begun.
- if (mEndVsyncId == mBeginVsyncId || mBeginVsyncId == INVALID_ID) {
- cancel();
+ if (mBeginVsyncId == INVALID_ID) {
+ cancel(REASON_CANCEL_NOT_BEGUN);
+ } else if (mEndVsyncId == mBeginVsyncId) {
+ cancel(REASON_CANCEL_SAME_VSYNC);
} else {
+ if (DEBUG) {
+ Log.d(TAG, "end: " + mSession.getName()
+ + ", end=" + mEndVsyncId + ", reason=" + reason);
+ }
Trace.endAsyncSection(mSession.getName(), (int) mBeginVsyncId);
+ mSession.setReason(reason);
+ InteractionJankMonitor.getInstance().removeTimeout(mSession.getCuj());
}
// We don't remove observer here,
// will remove it when all the frame metrics in this duration are called back.
@@ -205,7 +250,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
/**
* Cancel the trace session of the CUJ.
*/
- public synchronized void cancel() {
+ public synchronized void cancel(@Reasons int reason) {
// We don't need to end the trace section if it never begun.
if (mBeginVsyncId != INVALID_ID) {
Trace.endAsyncSection(mSession.getName(), (int) mBeginVsyncId);
@@ -215,10 +260,16 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
// Always remove the observers in cancel call to avoid leakage.
removeObservers();
+ if (DEBUG) {
+ Log.d(TAG, "cancel: " + mSession.getName()
+ + ", begin=" + mBeginVsyncId + ", end=" + mEndVsyncId + ", reason=" + reason);
+ }
+
+ mSession.setReason(reason);
// Notify the listener the session has been cancelled.
// We don't notify the listeners if the session never begun.
- if (mListener != null && mBeginVsyncId != INVALID_ID) {
- mListener.onNotifyCujEvents(mSession, InteractionJankMonitor.ACTION_SESSION_CANCEL);
+ if (mListener != null) {
+ mListener.onNotifyCujEvents(mSession, ACTION_SESSION_CANCEL);
}
}
@@ -399,6 +450,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
}
if (DEBUG) {
Log.i(TAG, "FrameTracker: CUJ=" + mSession.getName()
+ + " (" + mBeginVsyncId + "," + mEndVsyncId + ")"
+ " totalFrames=" + totalFramesCount
+ " missedAppFrames=" + missedAppFramesCount
+ " missedSfFrames=" + missedSfFramesCounts
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index fbc92c1f99c4..6c56d421a1fb 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -19,6 +19,7 @@ package com.android.internal.jank;
import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
import static com.android.internal.jank.FrameTracker.ChoreographerWrapper;
+import static com.android.internal.jank.FrameTracker.REASON_CANCEL_NOT_BEGUN;
import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
@@ -104,7 +105,7 @@ public class InteractionJankMonitor {
public static final String BUNDLE_KEY_CUJ_NAME = ACTION_PREFIX + ".CUJ_NAME";
public static final String BUNDLE_KEY_TIMESTAMP = ACTION_PREFIX + ".TIMESTAMP";
@VisibleForTesting
- public static final String PROP_NOTIFY_CUJ_EVENT = "debug.notify_cuj_events";
+ public static final String PROP_NOTIFY_CUJ_EVENT = "debug.jank.notify_cuj_events";
// Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0;
@@ -287,6 +288,10 @@ public class InteractionJankMonitor {
}
private void notifyEvents(Context context, String action, Session session) {
+ if (action.equals(ACTION_SESSION_CANCEL)
+ && session.getReason() == REASON_CANCEL_NOT_BEGUN) {
+ return;
+ }
Intent intent = new Intent(action);
intent.putExtra(BUNDLE_KEY_CUJ_NAME, getNameOfCuj(session.getCuj()));
intent.putExtra(BUNDLE_KEY_TIMESTAMP, session.getTimeStamp());
@@ -294,6 +299,16 @@ public class InteractionJankMonitor {
context.sendBroadcast(intent);
}
+ void removeTimeout(@CujType int cujType) {
+ synchronized (this) {
+ Runnable timeout = mTimeoutActions.get(cujType);
+ if (timeout != null) {
+ mWorker.getThreadHandler().removeCallbacks(timeout);
+ mTimeoutActions.remove(cujType);
+ }
+ }
+ }
+
/**
* Begin a trace session.
*
@@ -351,16 +366,11 @@ public class InteractionJankMonitor {
synchronized (this) {
// remove the timeout action first.
- Runnable timeout = mTimeoutActions.get(cujType);
- if (timeout != null) {
- mWorker.getThreadHandler().removeCallbacks(timeout);
- mTimeoutActions.remove(cujType);
- }
-
+ removeTimeout(cujType);
FrameTracker tracker = getTracker(cujType);
// Skip this call since we haven't started a trace yet.
if (tracker == null) return false;
- tracker.end();
+ tracker.end(FrameTracker.REASON_END_NORMAL);
mRunningTrackers.remove(cujType);
return true;
}
@@ -375,16 +385,11 @@ public class InteractionJankMonitor {
//TODO (163505250): This should be no-op if not in droid food rom.
synchronized (this) {
// remove the timeout action first.
- Runnable timeout = mTimeoutActions.get(cujType);
- if (timeout != null) {
- mWorker.getThreadHandler().removeCallbacks(timeout);
- mTimeoutActions.remove(cujType);
- }
-
+ removeTimeout(cujType);
FrameTracker tracker = getTracker(cujType);
// Skip this call since we haven't started a trace yet.
if (tracker == null) return false;
- tracker.cancel();
+ tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL);
mRunningTrackers.remove(cujType);
return true;
}
@@ -509,6 +514,8 @@ public class InteractionJankMonitor {
@CujType
private int mCujType;
private long mTimeStamp;
+ @FrameTracker.Reasons
+ private int mReason = FrameTracker.REASON_END_UNKNOWN;
public Session(@CujType int cujType) {
mCujType = cujType;
@@ -543,5 +550,13 @@ public class InteractionJankMonitor {
public long getTimeStamp() {
return mTimeStamp;
}
+
+ public void setReason(@FrameTracker.Reasons int reason) {
+ mReason = reason;
+ }
+
+ public int getReason() {
+ return mReason;
+ }
}
}
diff --git a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
index 586607e413d9..2f4958223270 100644
--- a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
+++ b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
@@ -44,14 +44,15 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+ final long measuredEnergyUC = batteryStats.getScreenDozeMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredEnergyUC, query);
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
- final double powerMah = getMeasuredOrEstimatedPower(
- batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(),
- mPowerEstimator, durationMs, query.shouldForceUsePowerProfileModel());
+ final double powerMah = getMeasuredOrEstimatedPower(powerModel,
+ measuredEnergyUC, mPowerEstimator, durationMs);
builder.getOrCreateSystemBatteryConsumerBuilder(
SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah, powerModel)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, durationMs);
}
@@ -64,10 +65,12 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator {
@Override
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
+ final long measuredEnergyUC = batteryStats.getScreenDozeMeasuredBatteryConsumptionUC();
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs, statsType);
- final double powerMah = getMeasuredOrEstimatedPower(
+ final int powerModel = getPowerModel(measuredEnergyUC);
+ final double powerMah = getMeasuredOrEstimatedPower(powerModel,
batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(),
- mPowerEstimator, durationMs, false);
+ mPowerEstimator, durationMs);
if (powerMah > 0) {
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.AMBIENT_DISPLAY, null, 0);
bs.usagePowerMah = powerMah;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b0920b0100da..ac72d290b8b2 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,7 +41,6 @@ import android.net.NetworkStats;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
-import android.os.BatteryProperty;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Build;
@@ -58,7 +57,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
@@ -150,14 +148,6 @@ import java.util.concurrent.locks.ReentrantLock;
public class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
-
- // TODO(b/169376495): STOPSHIP if true
- private static final boolean DEBUG_FOREGROUND_STATS = true;
-
- private static final boolean ENABLE_FOREGROUND_STATS_COLLECTION =
- DEBUG_FOREGROUND_STATS && SystemProperties.getBoolean(
- "debug.battery_foreground_stats_collection", false);
-
public static final boolean DEBUG_ENERGY = false;
private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
private static final boolean DEBUG_BINDER_STATS = false;
@@ -752,37 +742,6 @@ public class BatteryStatsImpl extends BatteryStats {
long mTrackRunningHistoryElapsedRealtimeMs = 0;
long mTrackRunningHistoryUptimeMs = 0;
- private static final int FOREGROUND_UID_INITIAL_CAPACITY = 10;
- private static final int INVALID_UID = -1;
-
- private final IntArray mForegroundUids = ENABLE_FOREGROUND_STATS_COLLECTION
- ? new IntArray(FOREGROUND_UID_INITIAL_CAPACITY) : null;
-
- // Last recorded battery energy capacity.
- // This is used for computing foregrund power per application.
- // See: PowerForUid below
- private long mLastBatteryEnergyCapacityNwh = 0;
-
- private static final class PowerForUid {
- public long energyNwh = 0;
- // Same as energyNwh, but not tracked for the first 2 minutes;
- public long filteredEnergyNwh = 0;
- public double totalHours = 0;
- public long baseTimeMs = 0;
-
- double computePower() {
- // units in nW
- return totalHours != 0 ? energyNwh / totalHours : -1.0;
- }
-
- double computeFilteredPower() {
- // units in nW
- return totalHours != 0 ? filteredEnergyNwh / totalHours : -1.0;
- }
- }
- private final HashMap<Integer, PowerForUid> mUidToPower = ENABLE_FOREGROUND_STATS_COLLECTION
- ? new HashMap<>() : null;
-
@NonNull
final BatteryStatsHistory mBatteryStatsHistory;
@@ -1094,7 +1053,6 @@ public class BatteryStatsImpl extends BatteryStats {
private int mNumConnectivityChange;
private int mBatteryVoltageMv = -1;
- private int mBatteryChargeUah = -1;
private int mEstimatedBatteryCapacityMah = -1;
private int mMinLearnedBatteryCapacityUah = -1;
@@ -4020,49 +3978,6 @@ public class BatteryStatsImpl extends BatteryStats {
// TODO(b/155216561): It is possible for isolated uids to be in a higher
// state than its parent uid. We should track the highest state within the union of host
// and isolated uids rather than only the parent uid.
-
-
- int uidState = mapToInternalProcessState(state);
-
- boolean isForeground = (uidState == Uid.PROCESS_STATE_TOP)
- || (uidState == Uid.PROCESS_STATE_FOREGROUND);
-
-
- if (ENABLE_FOREGROUND_STATS_COLLECTION) {
- boolean previouslyInForegrond = false;
- for (int i = 0; i < mForegroundUids.size(); i++) {
- if (mForegroundUids.get(i) == uid) {
- previouslyInForegrond = true;
- if (!isForeground) {
- // If we were previously in the foreground, remove the uid
- // from the foreground set and dirty the slot.
- mForegroundUids.set(i, INVALID_UID);
- final PowerForUid pfu =
- mUidToPower.computeIfAbsent(uid, unused -> new PowerForUid());
- pfu.baseTimeMs = 0;
- break;
- }
- }
- }
-
- if (!previouslyInForegrond && isForeground) {
- boolean addedToForeground = false;
- // Check if we have a free slot to clobber...
- for (int i = 0; i < mForegroundUids.size(); i++) {
- if (mForegroundUids.get(i) == INVALID_UID) {
- addedToForeground = true;
- mForegroundUids.set(i, uid);
- break;
- }
- }
-
- // ...if not, append to the end of the array.
- if (!addedToForeground) {
- mForegroundUids.add(uid);
- }
- }
- }
-
FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
ActivityManager.processStateAmToProto(state));
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -13547,7 +13462,6 @@ public class BatteryStatsImpl extends BatteryStats {
doWrite = true;
resetAllStatsLocked(mSecUptime, mSecRealtime);
if (chargeUah > 0 && level > 0) {
- mBatteryChargeUah = chargeUah;
// Only use the reported coulomb charge value if it is supported and reported.
mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
}
@@ -13720,48 +13634,7 @@ public class BatteryStatsImpl extends BatteryStats {
startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
}
-
mBatteryVoltageMv = voltageMv;
-
- if (ENABLE_FOREGROUND_STATS_COLLECTION) {
- if (onBattery) {
- final long energyNwh = (voltageMv * (long) chargeUah);
- final long energyDelta = mLastBatteryEnergyCapacityNwh - energyNwh;
- for (int i = 0; i < mForegroundUids.size(); i++) {
- final int uid = mForegroundUids.get(i);
- if (uid == INVALID_UID) {
- continue;
- }
- final PowerForUid pfu = mUidToPower
- .computeIfAbsent(uid, unused -> new PowerForUid());
- if (pfu.baseTimeMs <= 0) {
- pfu.baseTimeMs = currentTimeMs;
- } else {
- // Check if mLastBatteryEnergyCapacityNwh > energyNwh,
- // to make sure we only count discharges
- if (energyDelta > 0) {
- pfu.energyNwh += energyDelta;
- // Convert from milliseconds to hours
- // 1000 ms per second * 3600 seconds per hour
- pfu.totalHours += ((double) (currentTimeMs - pfu.baseTimeMs)
- / (1.0 * 1000 * 60 * 60));
- // Now convert from 2 minutes to hours
- // 2 minutes = 1/30 of an hour
- if (pfu.totalHours > (2.0 / 60)) {
- pfu.filteredEnergyNwh += energyDelta;
- }
-
- }
- pfu.baseTimeMs = currentTimeMs;
- }
- }
- mLastBatteryEnergyCapacityNwh = energyNwh;
- } else if (onBattery != mOnBattery) {
- // Transition to onBattery = false
- mUidToPower.values().forEach(v -> v.baseTimeMs = 0);
- }
- }
-
mCurrentBatteryLevel = level;
if (mDischargePlugLevel < 0) {
mDischargePlugLevel = level;
@@ -16679,48 +16552,6 @@ public class BatteryStatsImpl extends BatteryStats {
}
public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
- if (ENABLE_FOREGROUND_STATS_COLLECTION) {
- long actualChargeUah = -1;
- long actualEnergyNwh = -1;
- try {
- IBatteryPropertiesRegistrar registrar =
- IBatteryPropertiesRegistrar.Stub.asInterface(
- ServiceManager.getService("batteryproperties"));
- if (registrar != null) {
- BatteryProperty prop = new BatteryProperty();
- if (registrar.getProperty(
- BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, prop) == 0) {
- actualChargeUah = prop.getLong();
- }
- prop = new BatteryProperty();
- if (registrar.getProperty(
- BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER, prop) == 0) {
- actualEnergyNwh = prop.getLong();
- }
- }
- } catch (RemoteException e) {
- // Ignore.
- }
- pw.printf("ActualCharge (uAh): %d\n", (int) actualChargeUah);
- pw.printf("ActualEnergy (nWh): %d\n", actualEnergyNwh);
- pw.printf("mBatteryCharge (uAh): %d\n", mBatteryChargeUah);
- pw.printf("mBatteryVolts (mV): %d\n", mBatteryVoltageMv);
- pw.printf("est energy (nWh): %d\n", mBatteryVoltageMv * (long) mBatteryChargeUah);
- pw.printf("mEstimatedBatteryCapacity (mAh): %d\n", mEstimatedBatteryCapacityMah);
- pw.printf("mMinLearnedBatteryCapacity (uAh): %d\n", mMinLearnedBatteryCapacityUah);
- pw.printf("mMaxLearnedBatteryCapacity (uAh): %d\n", mMaxLearnedBatteryCapacityUah);
- pw.printf("est. capacity: %f\n",
- (float) actualChargeUah / (mEstimatedBatteryCapacityMah * 1000));
- pw.printf("mCurrentBatteryLevel: %d\n", mCurrentBatteryLevel);
- pw.println("Total Power per app:");
- mUidToPower.entrySet().forEach(e ->
- pw.printf("Uid: %d, Total watts (nW): %f\n",
- e.getKey(), e.getValue().computePower()));
- pw.println("Total Power per app after first 2 minutes initial launch:");
- mUidToPower.entrySet().forEach(e ->
- pw.printf("Uid: %d, Total watts (nW): %f\n",
- e.getKey(), e.getValue().computeFilteredPower()));
- }
if (DEBUG) {
pw.println("mOnBatteryTimeBase:");
mOnBatteryTimeBase.dump(pw, " ");
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index f8ae0c1858f8..49c564b8a737 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -132,9 +132,12 @@ public class BatteryUsageStatsProvider {
// TODO(b/174186358): read extra time component number from configuration
final int customTimeComponentCount = 0;
- final BatteryUsageStats.Builder batteryUsageStatsBuilder =
- new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount)
- .setStatsStartTimestamp(mStats.getStartClockTime());
+ final boolean includePowerModels = (query.getFlags()
+ & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
+
+ final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
+ customPowerComponentCount, customTimeComponentCount, includePowerModels);
+ batteryUsageStatsBuilder.setStatsStartTimestamp(mStats.getStartClockTime());
SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
for (int i = uidStats.size() - 1; i >= 0; i--) {
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 14b870575769..30a35367d6f5 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -57,6 +57,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
public static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false;
public static final boolean DEFAULT_TRACK_DIRECT_CALLING_UID = true;
public static final boolean DEFAULT_IGNORE_BATTERY_STATUS = false;
+ public static final boolean DEFAULT_COLLECT_LATENCY_DATA = false;
public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 1500;
private static final String DEBUG_ENTRY_PREFIX = "__DEBUG_";
@@ -97,11 +98,13 @@ public class BinderCallsStats implements BinderInternal.Observer {
private boolean mTrackDirectCallingUid = DEFAULT_TRACK_DIRECT_CALLING_UID;
private boolean mTrackScreenInteractive = DEFAULT_TRACK_SCREEN_INTERACTIVE;
private boolean mIgnoreBatteryStatus = DEFAULT_IGNORE_BATTERY_STATUS;
+ private boolean mCollectLatencyData = DEFAULT_COLLECT_LATENCY_DATA;
private CachedDeviceState.Readonly mDeviceState;
private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch;
private static final int CALL_STATS_OBSERVER_DEBOUNCE_MILLIS = 5000;
+ private BinderLatencyObserver mLatencyObserver;
private BinderInternal.CallStatsObserver mCallStatsObserver;
private ArraySet<Integer> mSendUidsToObserver = new ArraySet<>(32);
private final Handler mCallStatsObserverHandler;
@@ -153,11 +156,16 @@ public class BinderCallsStats implements BinderInternal.Observer {
public Handler getHandler() {
return new Handler(Looper.getMainLooper());
}
+
+ public BinderLatencyObserver getLatencyObserver() {
+ return new BinderLatencyObserver(new BinderLatencyObserver.Injector());
+ }
}
public BinderCallsStats(Injector injector) {
this.mRandom = injector.getRandomGenerator();
this.mCallStatsObserverHandler = injector.getHandler();
+ this.mLatencyObserver = injector.getLatencyObserver();
}
public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
@@ -207,7 +215,10 @@ public class BinderCallsStats implements BinderInternal.Observer {
if (mRecordingAllTransactionsForUid || s.recordedCall) {
s.cpuTimeStarted = getThreadTimeMicro();
s.timeStarted = getElapsedRealtimeMicro();
+ } else if (mCollectLatencyData) {
+ s.timeStarted = getElapsedRealtimeMicro();
}
+
return s;
}
@@ -232,6 +243,10 @@ public class BinderCallsStats implements BinderInternal.Observer {
private void processCallEnded(CallSession s,
int parcelRequestSize, int parcelReplySize, int workSourceUid) {
+ if (mCollectLatencyData) {
+ mLatencyObserver.callEnded(s);
+ }
+
UidEntry uidEntry = null;
final boolean recordCall;
if (s.recordedCall) {
@@ -757,6 +772,17 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
}
+ /** Whether to collect latency histograms. */
+ public void setCollectLatencyData(boolean collectLatencyData) {
+ mCollectLatencyData = collectLatencyData;
+ }
+
+ /** Whether to collect latency histograms. */
+ @VisibleForTesting
+ public boolean getCollectLatencyData() {
+ return mCollectLatencyData;
+ }
+
public void reset() {
synchronized (mLock) {
mCallStatsCount = 0;
@@ -768,6 +794,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
mBatteryStopwatch.reset();
}
mRecordingAllTransactionsForUid = false;
+ // Do not reset the latency observer as binder stats and latency will be pushed to WW
+ // at different intervals so the resets should not be coupled.
}
}
@@ -1009,6 +1037,10 @@ public class BinderCallsStats implements BinderInternal.Observer {
return mExceptionCounts;
}
+ public BinderLatencyObserver getLatencyObserver() {
+ return mLatencyObserver;
+ }
+
@VisibleForTesting
public static <T> List<T> getHighestValues(List<T> list, ToDoubleFunction<T> toDouble,
double percentile) {
diff --git a/core/java/com/android/internal/os/BinderLatencyObserver.java b/core/java/com/android/internal/os/BinderLatencyObserver.java
new file mode 100644
index 000000000000..92b495284de2
--- /dev/null
+++ b/core/java/com/android/internal/os/BinderLatencyObserver.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.Nullable;
+import android.os.Binder;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BinderInternal.CallSession;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+/** Collects statistics about Binder call latency per calling API and method. */
+public class BinderLatencyObserver {
+ private static final String TAG = "BinderLatencyObserver";
+ public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 10;
+
+ // This is not the final data structure - we will eventually store latency histograms instead of
+ // raw samples as it is much more memory / disk space efficient.
+ // TODO(b/179999191): change this to store the histogram.
+ // TODO(b/179999191): pre allocate the array size so we would not have to resize this.
+ @GuardedBy("mLock")
+ private final ArrayMap<LatencyDims, ArrayList<Long>> mLatencySamples = new ArrayMap<>();
+ private final Object mLock = new Object();
+
+ // Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
+ // of 100 requests.
+ private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
+ private final Random mRandom;
+
+ /** Injector for {@link BinderLatencyObserver}. */
+ public static class Injector {
+ public Random getRandomGenerator() {
+ return new Random();
+ }
+ }
+
+ public BinderLatencyObserver(Injector injector) {
+ mRandom = injector.getRandomGenerator();
+ }
+
+ /** Should be called when a Binder call completes, will store latency data. */
+ public void callEnded(@Nullable CallSession s) {
+ if (s == null || s.exceptionThrown || !shouldKeepSample()) {
+ return;
+ }
+
+ LatencyDims dims = new LatencyDims(s.binderClass, s.transactionCode);
+ long callDuration = getElapsedRealtimeMicro() - s.timeStarted;
+
+ synchronized (mLock) {
+ if (!mLatencySamples.containsKey(dims)) {
+ mLatencySamples.put(dims, new ArrayList<Long>());
+ }
+
+ mLatencySamples.get(dims).add(callDuration);
+ }
+ }
+
+ protected long getElapsedRealtimeMicro() {
+ return SystemClock.elapsedRealtimeNanos() / 1000;
+ }
+
+ protected boolean shouldKeepSample() {
+ return mRandom.nextInt() % mPeriodicSamplingInterval == 0;
+ }
+
+ /** Updates the sampling interval. */
+ public void setSamplingInterval(int samplingInterval) {
+ if (samplingInterval <= 0) {
+ Slog.w(TAG, "Ignored invalid sampling interval (value must be positive): "
+ + samplingInterval);
+ return;
+ }
+
+ synchronized (mLock) {
+ if (samplingInterval != mPeriodicSamplingInterval) {
+ mPeriodicSamplingInterval = samplingInterval;
+ reset();
+ }
+ }
+ }
+
+ /** Resets the sample collection. */
+ public void reset() {
+ synchronized (mLock) {
+ mLatencySamples.clear();
+ }
+ }
+
+ /** Container for binder latency information. */
+ public static class LatencyDims {
+ // Binder interface descriptor.
+ private Class<? extends Binder> mBinderClass;
+ // Binder transaction code.
+ private int mTransactionCode;
+ // Cached hash code, 0 if not set yet.
+ private int mHashCode = 0;
+
+ public LatencyDims(Class<? extends Binder> binderClass, int transactionCode) {
+ this.mBinderClass = binderClass;
+ this.mTransactionCode = transactionCode;
+ }
+
+ public Class<? extends Binder> getBinderClass() {
+ return mBinderClass;
+ }
+
+ public int getTransactionCode() {
+ return mTransactionCode;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (other == null || !(other instanceof LatencyDims)) {
+ return false;
+ }
+ LatencyDims o = (LatencyDims) other;
+ return mTransactionCode == o.getTransactionCode() && mBinderClass == o.getBinderClass();
+ }
+
+ @Override
+ public int hashCode() {
+ if (mHashCode != 0) {
+ return mHashCode;
+ }
+ int hash = mTransactionCode;
+ hash = 31 * hash + mBinderClass.hashCode();
+ mHashCode = hash;
+ return hash;
+ }
+ }
+
+ @VisibleForTesting
+ public ArrayMap<LatencyDims, ArrayList<Long>> getLatencySamples() {
+ return mLatencySamples;
+ }
+}
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 75a98133a8f3..a418dfff5d8f 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -15,8 +15,6 @@
*/
package com.android.internal.os;
-import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
-
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryStats.ControllerActivityCounter;
@@ -75,12 +73,13 @@ public class BluetoothPowerCalculator extends PowerCalculator {
}
}
- final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
- POWER_DATA_UNAVAILABLE : batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC, query);
final ControllerActivityCounter activityCounter =
batteryStats.getBluetoothControllerActivity();
final long systemDurationMs = calculateDuration(activityCounter);
- final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double systemPowerMah =
+ calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
// Subtract what the apps used, but clamp to 0.
final long systemComponentDurationMs = Math.max(0, systemDurationMs - total.durationMs);
@@ -92,23 +91,22 @@ public class BluetoothPowerCalculator extends PowerCalculator {
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
systemComponentDurationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
- Math.max(systemPowerMah, total.powerMah))
+ Math.max(systemPowerMah, total.powerMah), powerModel)
.setPowerConsumedByApps(total.powerMah);
}
private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total,
BatteryUsageStatsQuery query) {
-
- final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
- POWER_DATA_UNAVAILABLE :
+ final long measuredChargeUC =
app.getBatteryStatsUid().getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC, query);
final ControllerActivityCounter activityCounter =
app.getBatteryStatsUid().getBluetoothControllerActivity();
final long durationMs = calculateDuration(activityCounter);
- final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah, powerModel);
total.durationMs += durationMs;
total.powerMah += powerMah;
@@ -132,10 +130,12 @@ public class BluetoothPowerCalculator extends PowerCalculator {
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC);
final ControllerActivityCounter activityCounter =
batteryStats.getBluetoothControllerActivity();
final long systemDurationMs = calculateDuration(activityCounter);
- final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double systemPowerMah =
+ calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
// Subtract what the apps used, but clamp to 0.
final double powerMah = Math.max(0, systemPowerMah - total.powerMah);
@@ -165,9 +165,10 @@ public class BluetoothPowerCalculator extends PowerCalculator {
PowerAndDuration total) {
final long measuredChargeUC = u.getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC);
final ControllerActivityCounter activityCounter = u.getBluetoothControllerActivity();
final long durationMs = calculateDuration(activityCounter);
- final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
app.bluetoothRunningTimeMs = durationMs;
app.bluetoothPowerMah = powerMah;
@@ -189,10 +190,12 @@ public class BluetoothPowerCalculator extends PowerCalculator {
}
/** Returns bluetooth power usage based on the best data available. */
- private double calculatePowerMah(long measuredChargeUC, ControllerActivityCounter counter) {
- if (measuredChargeUC != POWER_DATA_UNAVAILABLE) {
+ private double calculatePowerMah(@BatteryConsumer.PowerModel int powerModel,
+ long measuredChargeUC, ControllerActivityCounter counter) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
return uCtoMah(measuredChargeUC);
}
+
if (counter == null) {
return 0;
}
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index b15543a26b4c..4aafec555182 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -91,10 +91,12 @@ public class CpuPowerCalculator extends PowerCalculator {
private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
BatteryUsageStatsQuery query, Result result) {
- calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED,
- query.shouldForceUsePowerProfileModel(), result);
+ final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculatePowerAndDuration(u, powerModel, consumptionUC, BatteryStats.STATS_SINCE_CHARGED,
+ result);
- app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah)
+ app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah, powerModel)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, result.durationMs)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND,
result.durationFgMs)
@@ -114,7 +116,9 @@ public class CpuPowerCalculator extends PowerCalculator {
}
private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType, Result result) {
- calculatePowerAndDuration(u, statsType, false, result);
+ final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculatePowerAndDuration(u, powerModel, consumptionUC, statsType, result);
app.cpuPowerMah = result.powerMah;
app.cpuTimeMs = result.durationMs;
@@ -122,16 +126,20 @@ public class CpuPowerCalculator extends PowerCalculator {
app.packageWithHighestDrain = result.packageWithHighestDrain;
}
- private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType,
- boolean forceUsePowerProfileModel, Result result) {
+ private void calculatePowerAndDuration(BatteryStats.Uid u,
+ @BatteryConsumer.PowerModel int powerModel, long consumptionUC, int statsType,
+ Result result) {
long durationMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
final double powerMah;
- final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
- if (forceUsePowerProfileModel || consumptionUC == BatteryStats.POWER_DATA_UNAVAILABLE) {
- powerMah = calculateUidModeledPowerMah(u, statsType);
- } else {
- powerMah = uCtoMah(consumptionUC);
+ switch(powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ powerMah = uCtoMah(consumptionUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ powerMah = calculateUidModeledPowerMah(u, statsType);
+ break;
}
if (DEBUG && (durationMs != 0 || powerMah != 0)) {
diff --git a/core/java/com/android/internal/os/DmabufInfoReader.java b/core/java/com/android/internal/os/DmabufInfoReader.java
new file mode 100644
index 000000000000..786a6eedf343
--- /dev/null
+++ b/core/java/com/android/internal/os/DmabufInfoReader.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.Nullable;
+
+/** Wrapper around libdmabufinfo. */
+public final class DmabufInfoReader {
+ private DmabufInfoReader() {}
+
+ /** Process dma-buf stats. */
+ public static final class ProcessDmabuf {
+ /** Size of buffers retained by the process. */
+ public final int retainedSizeKb;
+ /** Number of buffers retained by the process. */
+ public final int retainedBuffersCount;
+ /** Size of buffers mapped to the address space. */
+ public final int mappedSizeKb;
+ /** Count of buffers mapped to the address space. */
+ public final int mappedBuffersCount;
+
+ ProcessDmabuf(int retainedSizeKb, int retainedBuffersCount,
+ int mappedSizeKb, int mappedBuffersCount) {
+ this.retainedSizeKb = retainedSizeKb;
+ this.retainedBuffersCount = retainedBuffersCount;
+ this.mappedSizeKb = mappedSizeKb;
+ this.mappedBuffersCount = mappedBuffersCount;
+ }
+ }
+
+ /**
+ * Return stats for DMA-BUFs retained by process pid or null if the DMA-BUF
+ * stats could not be read.
+ */
+ @Nullable
+ public static native ProcessDmabuf getProcessStats(int pid);
+}
diff --git a/core/java/com/android/internal/os/GnssPowerCalculator.java b/core/java/com/android/internal/os/GnssPowerCalculator.java
index 97c4fd8b7b7a..0e0870de4f5f 100644
--- a/core/java/com/android/internal/os/GnssPowerCalculator.java
+++ b/core/java/com/android/internal/os/GnssPowerCalculator.java
@@ -52,28 +52,30 @@ public class GnssPowerCalculator extends PowerCalculator {
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, query,
- averageGnssPowerMa);
+ final long consumptionUC =
+ app.getBatteryStatsUid().getGnssMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateApp(app, app.getBatteryStatsUid(), powerModel, rawRealtimeUs,
+ averageGnssPowerMa, consumptionUC);
}
}
private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
- long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
- double averageGnssPowerMa) {
+ @BatteryConsumer.PowerModel int powerModel, long rawRealtimeUs,
+ double averageGnssPowerMa, long measuredChargeUC) {
final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
-
- final long measuredChargeUC = u.getGnssMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = !query.shouldForceUsePowerProfileModel()
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
-
final double powerMah;
- if (isMeasuredPowerAvailable) {
- powerMah = uCtoMah(measuredChargeUC);
- } else {
- powerMah = computePower(durationMs, averageGnssPowerMa);
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ powerMah = uCtoMah(measuredChargeUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ powerMah = computePower(durationMs, averageGnssPowerMa);
}
+
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_GNSS, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS, powerMah, powerModel);
}
@Override
@@ -83,24 +85,28 @@ public class GnssPowerCalculator extends PowerCalculator {
for (int i = sippers.size() - 1; i >= 0; i--) {
final BatterySipper app = sippers.get(i);
if (app.drainType == BatterySipper.DrainType.APP) {
- calculateApp(app, app.uidObj, rawRealtimeUs, statsType, averageGnssPowerMa, false);
+ final long consumptionUC =
+ app.uidObj.getGnssMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateApp(app, app.uidObj, powerModel, rawRealtimeUs, averageGnssPowerMa,
+ consumptionUC);
}
}
}
- protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
- int statsType, double averageGnssPowerMa, boolean shouldForceUsePowerProfileModel) {
+ private void calculateApp(BatterySipper app, BatteryStats.Uid u,
+ @BatteryConsumer.PowerModel int powerModel, long rawRealtimeUs,
+ double averageGnssPowerMa, long measuredChargeUC) {
final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
- final long measuredChargeUC = u.getGnssMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = shouldForceUsePowerProfileModel
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
-
final double powerMah;
- if (isMeasuredPowerAvailable) {
- powerMah = uCtoMah(measuredChargeUC);
- } else {
- powerMah = computePower(durationMs, averageGnssPowerMa);
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ powerMah = uCtoMah(measuredChargeUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ powerMah = computePower(durationMs, averageGnssPowerMa);
}
app.gpsTimeMs = durationMs;
diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
index f6ef30cba369..d441d4529aca 100644
--- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
+++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
@@ -97,37 +97,41 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
final BatteryStats.Uid uid = app.getBatteryStatsUid();
- calculateApp(app, uid, powerPerPacketMah, total,
- query.shouldForceUsePowerProfileModel());
+ calculateApp(app, uid, powerPerPacketMah, total, query);
}
- calculateRemaining(total, batteryStats, rawRealtimeUs,
- query.shouldForceUsePowerProfileModel());
+ final long consumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, consumptionUC);
if (total.remainingPowerMah != 0 || total.totalAppPowerMah != 0) {
builder.getOrCreateSystemBatteryConsumerBuilder(
- SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO)
+ SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_MOBILE_RADIO,
total.durationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
- total.remainingPowerMah + total.totalAppPowerMah)
+ total.remainingPowerMah + total.totalAppPowerMah,
+ powerModel)
.setPowerConsumedByApps(total.totalAppPowerMah);
}
}
private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
double powerPerPacketMah, PowerAndDuration total,
- boolean shouldForceUsePowerProfileModel) {
+ BatteryUsageStatsQuery query) {
final long radioActiveDurationMs = calculateDuration(u, BatteryStats.STATS_SINCE_CHARGED);
total.totalAppDurationMs += radioActiveDurationMs;
- final double powerMah = calculatePower(u, powerPerPacketMah, radioActiveDurationMs,
- shouldForceUsePowerProfileModel);
+ final long consumptionUC = u.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ final double powerMah = calculatePower(u, powerModel, powerPerPacketMah,
+ radioActiveDurationMs, consumptionUC);
total.totalAppPowerMah += powerMah;
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_MOBILE_RADIO,
- radioActiveDurationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, powerMah);
+ radioActiveDurationMs)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, powerMah,
+ powerModel);
}
@Override
@@ -140,12 +144,14 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
final BatterySipper app = sippers.get(i);
if (app.drainType == BatterySipper.DrainType.APP) {
final BatteryStats.Uid u = app.uidObj;
- calculateApp(app, u, statsType, mobilePowerPerPacket, total, false);
+ calculateApp(app, u, statsType, mobilePowerPerPacket, total);
}
}
BatterySipper radio = new BatterySipper(BatterySipper.DrainType.CELL, null, 0);
- calculateRemaining(total, batteryStats, rawRealtimeUs, false);
+ final long consumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, consumptionUC);
if (total.remainingPowerMah != 0) {
if (total.signalDurationMs != 0) {
radio.noCoveragePercent =
@@ -162,12 +168,13 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
}
private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType,
- double powerPerPacketMah, PowerAndDuration total,
- boolean shouldForceUsePowerProfileModel) {
+ double powerPerPacketMah, PowerAndDuration total) {
app.mobileActive = calculateDuration(u, statsType);
- app.mobileRadioPowerMah = calculatePower(u, powerPerPacketMah, app.mobileActive,
- shouldForceUsePowerProfileModel);
+ final long consumptionUC = u.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ app.mobileRadioPowerMah = calculatePower(u, powerModel, powerPerPacketMah, app.mobileActive,
+ consumptionUC);
total.totalAppDurationMs += app.mobileActive;
// Add cost of mobile traffic.
@@ -193,13 +200,9 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
return u.getMobileRadioActiveTime(statsType) / 1000;
}
- private double calculatePower(BatteryStats.Uid u, double powerPerPacketMah,
- long radioActiveDurationMs, boolean shouldForceUsePowerProfileModel) {
-
- final long measuredChargeUC = u.getMobileRadioMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = !shouldForceUsePowerProfileModel
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
+ private double calculatePower(BatteryStats.Uid u, @BatteryConsumer.PowerModel int powerModel,
+ double powerPerPacketMah, long radioActiveDurationMs, long measuredChargeUC) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
return uCtoMah(measuredChargeUC);
}
@@ -220,23 +223,20 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
}
}
- private void calculateRemaining(MobileRadioPowerCalculator.PowerAndDuration total,
- BatteryStats batteryStats, long rawRealtimeUs,
- boolean shouldForceUsePowerProfileModel) {
+ private void calculateRemaining(PowerAndDuration total,
+ @BatteryConsumer.PowerModel int powerModel, BatteryStats batteryStats,
+ long rawRealtimeUs, long consumptionUC) {
long signalTimeMs = 0;
double powerMah = 0;
- final long measuredChargeUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = !shouldForceUsePowerProfileModel
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
- powerMah = uCtoMah(measuredChargeUC);
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
+ powerMah = uCtoMah(consumptionUC);
}
for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
long strengthTimeMs = batteryStats.getPhoneSignalStrengthTime(i, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED) / 1000;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
final double p = calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i);
if (DEBUG && p != 0) {
Log.d(TAG, "Cell strength #" + i + ": time=" + strengthTimeMs + " power="
@@ -256,7 +256,7 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
BatteryStats.STATS_SINCE_CHARGED) / 1000;
long remainingActiveTimeMs = radioActiveTimeMs - total.totalAppDurationMs;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
final double p = calcScanTimePowerMah(scanningTimeMs);
if (DEBUG && p != 0) {
Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + formatCharge(
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index 72385e273cf0..d139b4f0aa9a 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.os;
+import android.annotation.NonNull;
+import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
@@ -114,19 +116,48 @@ public abstract class PowerCalculator {
public void reset() {
}
+ protected static @BatteryConsumer.PowerModel int getPowerModel(
+ long measuredEnergyUC, @NonNull BatteryUsageStatsQuery query) {
+ if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE
+ && !query.shouldForceUsePowerProfileModel()) {
+ return BatteryConsumer.POWER_MODEL_MEASURED_ENERGY;
+ }
+ return BatteryConsumer.POWER_MODEL_POWER_PROFILE;
+ }
+
+ protected static @BatteryConsumer.PowerModel int getPowerModel(long measuredEnergyUC) {
+ return measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE
+ ? BatteryConsumer.POWER_MODEL_MEASURED_ENERGY
+ : BatteryConsumer.POWER_MODEL_POWER_PROFILE;
+ }
+
/**
* Returns either the measured energy converted to mAh or a usage-based estimate.
*/
- protected static double getMeasuredOrEstimatedPower(long measuredEnergyUC,
- UsageBasedPowerEstimator powerEstimator, long durationMs,
- boolean forceUsePowerProfileModel) {
- if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE
- && !forceUsePowerProfileModel) {
+ protected static double getMeasuredOrEstimatedPower(@BatteryConsumer.PowerModel int powerModel,
+ long measuredEnergyUC, UsageBasedPowerEstimator powerEstimator, long durationMs) {
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ return uCtoMah(measuredEnergyUC);
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ return powerEstimator.calculatePower(durationMs);
+ }
+ }
+
+ /**
+ * Returns either the measured energy converted to mAh or a usage-based estimate.
+ */
+ protected static double getMeasuredOrEstimatedPower(
+ long measuredEnergyUC, UsageBasedPowerEstimator powerEstimator, long durationMs) {
+ if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE) {
return uCtoMah(measuredEnergyUC);
+ } else {
+ return powerEstimator.calculatePower(durationMs);
}
- return powerEstimator.calculatePower(durationMs);
}
+
/**
* Converts charge in mAh to string.
*/
diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java
index ad574440f216..0267def918c2 100644
--- a/core/java/com/android/internal/os/ScreenPowerCalculator.java
+++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java
@@ -62,9 +62,10 @@ public class ScreenPowerCalculator extends PowerCalculator {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final PowerAndDuration totalPowerAndDuration = new PowerAndDuration();
- final boolean useEnergyData = calculateTotalDurationAndPower(totalPowerAndDuration,
- batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED,
- query.shouldForceUsePowerProfileModel());
+ final long consumptionUC = batteryStats.getScreenOnMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateTotalDurationAndPower(totalPowerAndDuration, powerModel, batteryStats,
+ rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED, consumptionUC);
double totalAppPower = 0;
@@ -73,29 +74,32 @@ public class ScreenPowerCalculator extends PowerCalculator {
// but the method depends on the data source.
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
- if (useEnergyData) {
- final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
- for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
- final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.getBatteryStatsUid(),
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
+ for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
+ final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+ calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.getBatteryStatsUid(),
+ rawRealtimeUs);
+ app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN,
+ appPowerAndDuration.durationMs)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN,
+ appPowerAndDuration.powerMah, powerModel);
+ totalAppPower += appPowerAndDuration.powerMah;
+ }
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ smearScreenBatteryDrain(uidBatteryConsumerBuilders, totalPowerAndDuration,
rawRealtimeUs);
- app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN,
- appPowerAndDuration.durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN,
- appPowerAndDuration.powerMah);
- totalAppPower += appPowerAndDuration.powerMah;
- }
- } else {
- smearScreenBatteryDrain(uidBatteryConsumerBuilders, totalPowerAndDuration,
- rawRealtimeUs);
- totalAppPower = totalPowerAndDuration.powerMah;
+ totalAppPower = totalPowerAndDuration.powerMah;
}
builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_SCREEN)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE,
totalPowerAndDuration.durationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE,
- Math.max(totalPowerAndDuration.powerMah, totalAppPower))
+ Math.max(totalPowerAndDuration.powerMah, totalAppPower), powerModel)
.setPowerConsumedByApps(totalAppPower);
}
@@ -106,8 +110,10 @@ public class ScreenPowerCalculator extends PowerCalculator {
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
final PowerAndDuration totalPowerAndDuration = new PowerAndDuration();
- final boolean useEnergyData = calculateTotalDurationAndPower(totalPowerAndDuration,
- batteryStats, rawRealtimeUs, statsType, false);
+ final long consumptionUC = batteryStats.getScreenOnMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateTotalDurationAndPower(totalPowerAndDuration, powerModel, batteryStats,
+ rawRealtimeUs, statsType, consumptionUC);
if (totalPowerAndDuration.powerMah == 0) {
return;
}
@@ -121,41 +127,42 @@ public class ScreenPowerCalculator extends PowerCalculator {
// Now deal with each app's BatterySipper. The results are stored in the screenPowerMah
// field, which is considered smeared, but the method depends on the data source.
- if (useEnergyData) {
- final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
- for (int i = sippers.size() - 1; i >= 0; i--) {
- final BatterySipper app = sippers.get(i);
- if (app.drainType == BatterySipper.DrainType.APP) {
- calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.uidObj, rawRealtimeUs);
- app.screenPowerMah = appPowerAndDuration.powerMah;
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
+ for (int i = sippers.size() - 1; i >= 0; i--) {
+ final BatterySipper app = sippers.get(i);
+ if (app.drainType == BatterySipper.DrainType.APP) {
+ calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.uidObj,
+ rawRealtimeUs);
+ app.screenPowerMah = appPowerAndDuration.powerMah;
+ }
}
- }
- } else {
- smearScreenBatterySipper(sippers, bs, rawRealtimeUs);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ smearScreenBatterySipper(sippers, bs, rawRealtimeUs);
}
}
/**
- * Stores duration and power information in totalPowerAndDuration and returns true if measured
- * energy data is available and should be used by the model.
+ * Stores duration and power information in totalPowerAndDuration.
*/
- private boolean calculateTotalDurationAndPower(PowerAndDuration totalPowerAndDuration,
- BatteryStats batteryStats, long rawRealtimeUs, int statsType,
- boolean forceUsePowerProfileModel) {
+ private void calculateTotalDurationAndPower(PowerAndDuration totalPowerAndDuration,
+ @BatteryConsumer.PowerModel int powerModel, BatteryStats batteryStats,
+ long rawRealtimeUs, int statsType, long consumptionUC) {
totalPowerAndDuration.durationMs = calculateDuration(batteryStats, rawRealtimeUs,
statsType);
- if (!forceUsePowerProfileModel) {
- final long chargeUC = batteryStats.getScreenOnMeasuredBatteryConsumptionUC();
- if (chargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) {
- totalPowerAndDuration.powerMah = uCtoMah(chargeUC);
- return true;
- }
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ totalPowerAndDuration.powerMah = uCtoMah(consumptionUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ totalPowerAndDuration.powerMah = calculateTotalPowerFromBrightness(batteryStats,
+ rawRealtimeUs, statsType, totalPowerAndDuration.durationMs);
}
-
- totalPowerAndDuration.powerMah = calculateTotalPowerFromBrightness(batteryStats,
- rawRealtimeUs, statsType, totalPowerAndDuration.durationMs);
- return false;
}
private void calculateAppUsingMeasuredEnergy(PowerAndDuration appPowerAndDuration,
@@ -245,7 +252,8 @@ public class ScreenPowerCalculator extends PowerCalculator {
final long durationMs = activityTimeArray.get(app.getUid(), 0);
final double powerMah = totalScreenPowerMah * durationMs / totalActivityTimeMs;
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, powerMah,
+ BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
}
}
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index d95506b00677..11219eccddad 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -15,8 +15,6 @@
*/
package com.android.internal.os;
-import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
-
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
@@ -92,10 +90,12 @@ public class WifiPowerCalculator extends PowerCalculator {
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), rawRealtimeUs,
- BatteryStats.STATS_SINCE_CHARGED,
- batteryStats.hasWifiActivityReporting(),
- query.shouldForceUsePowerProfileModel());
+ final long consumptionUC =
+ app.getBatteryStatsUid().getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), powerModel,
+ rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED,
+ batteryStats.hasWifiActivityReporting(), consumptionUC);
totalAppDurationMs += powerDurationAndTraffic.durationMs;
totalAppPowerMah += powerDurationAndTraffic.powerMah;
@@ -103,7 +103,7 @@ public class WifiPowerCalculator extends PowerCalculator {
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
powerDurationAndTraffic.durationMs);
app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
- powerDurationAndTraffic.powerMah);
+ powerDurationAndTraffic.powerMah, powerModel);
if (app.getUid() == Process.WIFI_UID) {
systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
@@ -111,17 +111,17 @@ public class WifiPowerCalculator extends PowerCalculator {
}
}
- calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs,
- BatteryStats.STATS_SINCE_CHARGED,
- batteryStats.hasWifiActivityReporting(),
- query.shouldForceUsePowerProfileModel(),
- totalAppDurationMs, totalAppPowerMah);
+ final long consumptionUC = batteryStats.getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateRemaining(powerDurationAndTraffic, powerModel, batteryStats, rawRealtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED, batteryStats.hasWifiActivityReporting(),
+ totalAppDurationMs, totalAppPowerMah, consumptionUC);
systemBatteryConsumerBuilder
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
powerDurationAndTraffic.durationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
- totalAppPowerMah + powerDurationAndTraffic.powerMah)
+ totalAppPowerMah + powerDurationAndTraffic.powerMah, powerModel)
.setPowerConsumedByApps(totalAppPowerMah);
}
@@ -144,8 +144,11 @@ public class WifiPowerCalculator extends PowerCalculator {
for (int i = sippers.size() - 1; i >= 0; i--) {
final BatterySipper app = sippers.get(i);
if (app.drainType == BatterySipper.DrainType.APP) {
- calculateApp(powerDurationAndTraffic, app.uidObj, rawRealtimeUs, statsType,
- batteryStats.hasWifiActivityReporting(), /* force use power model*/ false);
+ final long consumptionUC =
+ app.uidObj.getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateApp(powerDurationAndTraffic, app.uidObj, powerModel, rawRealtimeUs,
+ statsType, batteryStats.hasWifiActivityReporting(), consumptionUC);
totalAppDurationMs += powerDurationAndTraffic.durationMs;
totalAppPowerMah += powerDurationAndTraffic.powerMah;
@@ -164,9 +167,11 @@ public class WifiPowerCalculator extends PowerCalculator {
}
}
- calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs, statsType,
- batteryStats.hasWifiActivityReporting(), /* force use power model*/ false,
- totalAppDurationMs, totalAppPowerMah);
+ final long consumptionUC = batteryStats.getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateRemaining(powerDurationAndTraffic, powerModel, batteryStats, rawRealtimeUs,
+ statsType, batteryStats.hasWifiActivityReporting(), totalAppDurationMs,
+ totalAppPowerMah, consumptionUC);
bs.wifiRunningTimeMs += powerDurationAndTraffic.durationMs;
bs.wifiPowerMah += powerDurationAndTraffic.powerMah;
@@ -176,9 +181,10 @@ public class WifiPowerCalculator extends PowerCalculator {
}
}
- private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic, BatteryStats.Uid u,
- long rawRealtimeUs, int statsType,
- boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel) {
+ private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic,
+ BatteryStats.Uid u, @BatteryConsumer.PowerModel int powerModel,
+ long rawRealtimeUs, int statsType, boolean hasWifiActivityReporting,
+ long consumptionUC) {
powerDurationAndTraffic.wifiRxPackets = u.getNetworkActivityPackets(
BatteryStats.NETWORK_WIFI_RX_DATA,
@@ -193,11 +199,8 @@ public class WifiPowerCalculator extends PowerCalculator {
BatteryStats.NETWORK_WIFI_TX_DATA,
statsType);
- final long measuredChargeUC = u.getWifiMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable
- = !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
- powerDurationAndTraffic.powerMah = uCtoMah(measuredChargeUC);
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
+ powerDurationAndTraffic.powerMah = uCtoMah(consumptionUC);
}
if (hasWifiActivityReporting && mHasWifiPowerController) {
@@ -208,7 +211,7 @@ public class WifiPowerCalculator extends PowerCalculator {
final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
powerDurationAndTraffic.durationMs = idleTime + rxTime + txTime;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
powerDurationAndTraffic.powerMah
= calcPowerFromControllerDataMah(rxTime, txTime, idleTime);
}
@@ -223,7 +226,7 @@ public class WifiPowerCalculator extends PowerCalculator {
final long wifiRunningTime = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
powerDurationAndTraffic.durationMs = wifiRunningTime;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
long batchTimeMs = 0;
for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
@@ -243,19 +246,17 @@ public class WifiPowerCalculator extends PowerCalculator {
}
private void calculateRemaining(PowerDurationAndTraffic powerDurationAndTraffic,
- BatteryStats stats, long rawRealtimeUs, int statsType,
- boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel,
- long totalAppDurationMs, double totalAppPowerMah) {
+ @BatteryConsumer.PowerModel int powerModel, BatteryStats stats, long rawRealtimeUs,
+ int statsType, boolean hasWifiActivityReporting, long totalAppDurationMs,
+ double totalAppPowerMah, long consumptionUC) {
long totalDurationMs;
double totalPowerMah = 0;
- final long measuredChargeUC = stats.getWifiMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable
- = !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
- totalPowerMah = uCtoMah(measuredChargeUC);
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
+ totalPowerMah = uCtoMah(consumptionUC);
}
+
if (hasWifiActivityReporting && mHasWifiPowerController) {
final BatteryStats.ControllerActivityCounter counter =
stats.getWifiControllerActivity();
@@ -266,7 +267,7 @@ public class WifiPowerCalculator extends PowerCalculator {
totalDurationMs = idleTimeMs + rxTimeMs + txTimeMs;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
totalPowerMah = counter.getPowerCounter().getCountLocked(statsType)
/ (double) (1000 * 60 * 60);
if (totalPowerMah == 0) {
@@ -276,7 +277,7 @@ public class WifiPowerCalculator extends PowerCalculator {
}
} else {
totalDurationMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType) / 1000;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
totalPowerMah = calcGlobalPowerWithoutControllerDataMah(totalDurationMs);
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5889f198a125..271c576c716e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -41,6 +41,7 @@ import android.os.UserHandle;
import android.os.ZygoteProcess;
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
+import android.security.keystore2.AndroidKeyStoreProvider;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -222,10 +223,8 @@ public class ZygoteInit {
long startTime = SystemClock.uptimeMillis();
Trace.traceBegin(
Trace.TRACE_TAG_DALVIK, "Starting installation of AndroidKeyStoreProvider");
- // AndroidKeyStoreProvider.install() manipulates the list of JCA providers to insert
- // preferred providers. Note this is not done via security.properties as the JCA providers
- // are not on the classpath in the case of, for example, raw dalvikvm runtimes.
- android.security.keystore2.AndroidKeyStoreProvider.install();
+
+ AndroidKeyStoreProvider.install();
Log.i(TAG, "Installed AndroidKeyStoreProvider in "
+ (SystemClock.uptimeMillis() - startTime) + "ms.");
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index f71b31493035..4d2266b2eba5 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -547,7 +547,7 @@ class ZygoteServer {
try {
ZygoteConnection connection = peers.get(pollIndex);
boolean multipleForksOK = !isUsapPoolEnabled()
- && ZygoteHooks.indefiniteThreadSuspensionOK();
+ && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
final Runnable command =
connection.processCommand(this, multipleForksOK);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 9a91d2028953..424632fe82eb 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -258,6 +258,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
private Drawable mLastOriginalBackgroundDrawable;
private Drawable mResizingBackgroundDrawable;
private BackgroundBlurDrawable mBackgroundBlurDrawable;
+ private BackgroundBlurDrawable mLastBackgroundBlurDrawable;
/**
* Temporary holder for a window background when it is set before {@link #mWindow} is
@@ -289,7 +290,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
private int mOriginalBackgroundBlurRadius = 0;
private int mBackgroundBlurRadius = 0;
- private int mLastBackgroundBlurRadius = 0;
private boolean mCrossWindowBlurEnabled;
private final ViewTreeObserver.OnPreDrawListener mBackgroundBlurOnPreDrawListener = () -> {
updateBackgroundBlurCorners();
@@ -1278,13 +1278,13 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
if (mBackgroundInsets.equals(mLastBackgroundInsets)
- && mBackgroundBlurRadius == mLastBackgroundBlurRadius
+ && mBackgroundBlurDrawable == mLastBackgroundBlurDrawable
&& mLastOriginalBackgroundDrawable == mOriginalBackgroundDrawable) {
return;
}
Drawable destDrawable = mOriginalBackgroundDrawable;
- if (mBackgroundBlurRadius > 0) {
+ if (mBackgroundBlurDrawable != null) {
destDrawable = new LayerDrawable(new Drawable[] {mBackgroundBlurDrawable,
mOriginalBackgroundDrawable});
}
@@ -1309,7 +1309,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
super.setBackgroundDrawable(destDrawable);
mLastBackgroundInsets = mBackgroundInsets;
- mLastBackgroundBlurRadius = mBackgroundBlurRadius;
+ mLastBackgroundBlurDrawable = mBackgroundBlurDrawable;
mLastOriginalBackgroundDrawable = mOriginalBackgroundDrawable;
}
@@ -1334,11 +1334,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
? mOriginalBackgroundBlurRadius : 0;
if (mBackgroundBlurDrawable == null && mBackgroundBlurRadius > 0) {
mBackgroundBlurDrawable = getViewRootImpl().createBackgroundBlurDrawable();
+ updateBackgroundDrawable();
}
if (mBackgroundBlurDrawable != null) {
mBackgroundBlurDrawable.setBlurRadius(mBackgroundBlurRadius);
- updateBackgroundDrawable();
}
}
@@ -1357,12 +1357,20 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
updateBackgroundBlurRadius();
}
} else if (mCrossWindowBlurEnabledListener != null) {
- mCrossWindowBlurEnabledListener = null;
+ updateBackgroundBlurRadius();
+ removeBackgroundBlurDrawable();
+ }
+ }
+
+ void removeBackgroundBlurDrawable() {
+ if (mCrossWindowBlurEnabledListener != null) {
getContext().getSystemService(WindowManager.class)
.removeCrossWindowBlurEnabledListener(mCrossWindowBlurEnabledListener);
- getViewTreeObserver().removeOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
- updateBackgroundBlurRadius();
+ mCrossWindowBlurEnabledListener = null;
}
+ getViewTreeObserver().removeOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
+ mBackgroundBlurDrawable = null;
+ updateBackgroundDrawable();
}
@Override
@@ -1847,6 +1855,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
mFloatingToolbar = null;
}
+ removeBackgroundBlurDrawable();
+
PhoneWindow.PanelFeatureState st = mWindow.getPanelState(Window.FEATURE_OPTIONS_PANEL, false);
if (st != null && st.menu != null && mFeatureId < 0) {
st.menu.close();
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 611fe29f4fcf..a6dc4e04bf36 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -75,6 +75,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.util.TypedValue;
+import android.view.ViewRoot;
import android.view.ContextThemeWrapper;
import android.view.CrossWindowBlurListeners;
import android.view.Gravity;
@@ -3981,4 +3982,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
public View getNavigationBarBackgroundView() {
return mDecor != null ? mDecor.getNavigationBarBackgroundView() : null;
}
+
+ @Override
+ public ViewRoot getViewRoot() {
+ return getViewRootImplOrNull();
+ }
}
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index c33637353984..8d82e33dc29f 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -35,7 +35,8 @@ import com.android.internal.view.InlineSuggestionsRequestInfo;
* {@hide}
*/
oneway interface IInputMethod {
- void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps);
+ void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps,
+ int configChanges);
void onCreateInlineSuggestionsRequest(in InlineSuggestionsRequestInfo requestInfo,
in IInlineSuggestionsRequestCallback cb);
diff --git a/core/java/com/android/internal/widget/RecyclerView.java b/core/java/com/android/internal/widget/RecyclerView.java
index 17ce75e63b6f..9ed5eb1d144e 100644
--- a/core/java/com/android/internal/widget/RecyclerView.java
+++ b/core/java/com/android/internal/widget/RecyclerView.java
@@ -2049,17 +2049,19 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro
}
if (!dispatchNestedPreFling(velocityX, velocityY)) {
- final View firstChild = mLayout.getChildAt(0);
- final View lastChild = mLayout.getChildAt(mLayout.getChildCount() - 1);
boolean consumed = false;
- if (velocityY < 0) {
- consumed = getChildAdapterPosition(firstChild) > 0
- || firstChild.getTop() < getPaddingTop();
- }
+ if (mLayout.getChildCount() > 0) {
+ final View firstChild = mLayout.getChildAt(0);
+ final View lastChild = mLayout.getChildAt(mLayout.getChildCount() - 1);
+ if (velocityY < 0) {
+ consumed = getChildAdapterPosition(firstChild) > 0
+ || firstChild.getTop() < getPaddingTop();
+ }
- if (velocityY > 0) {
- consumed = getChildAdapterPosition(lastChild) < mAdapter.getItemCount() - 1
- || lastChild.getBottom() > getHeight() - getPaddingBottom();
+ if (velocityY > 0) {
+ consumed = getChildAdapterPosition(lastChild) < mAdapter.getItemCount() - 1
+ || lastChild.getBottom() > getHeight() - getPaddingBottom();
+ }
}
dispatchNestedFling(velocityX, velocityY, consumed);