diff options
241 files changed, 3520 insertions, 2838 deletions
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java index 0dde546e85de..9bd57a1109de 100644 --- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java +++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java @@ -17,6 +17,7 @@ package com.android.server; import android.annotation.Nullable; +import android.os.PowerWhitelistManager; import android.os.PowerWhitelistManager.ReasonCode; import android.os.PowerWhitelistManager.TempAllowListType; @@ -32,11 +33,22 @@ public interface DeviceIdleInternal { void exitIdle(String reason); + /** + * Same as {@link #addPowerSaveTempWhitelistApp(int, String, long, int, boolean, int, String)} + * with {@link PowerWhitelistManager#TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED}. + */ void addPowerSaveTempWhitelistApp(int callingUid, String packageName, long durationMs, int userId, boolean sync, @ReasonCode int reasonCode, @Nullable String reason); /** + * Put a package in the temp-allowlist. + */ + void addPowerSaveTempWhitelistApp(int callingUid, String packageName, + long durationMs, @TempAllowListType int tempAllowListType, int userId, boolean sync, + @ReasonCode int reasonCode, @Nullable String reason); + + /** * Called by ActivityManagerService to directly add UID to DeviceIdleController's temp * allowlist. * @param uid diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 84fb39b273c4..119dcb63770d 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -1942,22 +1942,29 @@ public class DeviceIdleController extends SystemService exitIdleInternal(reason); } - // duration in milliseconds @Override public void addPowerSaveTempWhitelistApp(int callingUid, String packageName, long durationMs, int userId, boolean sync, @ReasonCode int reasonCode, @Nullable String reason) { addPowerSaveTempAllowlistAppInternal(callingUid, packageName, durationMs, + TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, userId, sync, reasonCode, reason); } - // duration in milliseconds @Override - public void addPowerSaveTempWhitelistAppDirect(int uid, long duration, - @TempAllowListType int type, boolean sync, @ReasonCode int reasonCode, + public void addPowerSaveTempWhitelistApp(int callingUid, String packageName, + long durationMs, @TempAllowListType int tempAllowListType, int userId, boolean sync, + @ReasonCode int reasonCode, @Nullable String reason) { + addPowerSaveTempAllowlistAppInternal(callingUid, packageName, durationMs, + tempAllowListType, userId, sync, reasonCode, reason); + } + + @Override + public void addPowerSaveTempWhitelistAppDirect(int uid, long durationMs, + @TempAllowListType int tempAllowListType, boolean sync, @ReasonCode int reasonCode, @Nullable String reason, int callingUid) { - addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration, type, sync, - reasonCode, reason); + addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, durationMs, + tempAllowListType, sync, reasonCode, reason); } // duration in milliseconds @@ -2699,7 +2706,8 @@ public class DeviceIdleController extends SystemService final long token = Binder.clearCallingIdentity(); try { addPowerSaveTempAllowlistAppInternal(callingUid, - packageName, duration, userId, true, reasonCode, reason); + packageName, duration, TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + userId, true, reasonCode, reason); } finally { Binder.restoreCallingIdentity(token); } @@ -2731,8 +2739,8 @@ public class DeviceIdleController extends SystemService * app an exemption to access network and acquire wakelocks. */ void addPowerSaveTempAllowlistAppInternal(int callingUid, String packageName, - long duration, int userId, boolean sync, @ReasonCode int reasonCode, - @Nullable String reason) { + long durationMs, @TempAllowListType int tempAllowListType, int userId, boolean sync, + @ReasonCode int reasonCode, @Nullable String reason) { synchronized (this) { int callingAppId = UserHandle.getAppId(callingUid); if (callingAppId >= Process.FIRST_APPLICATION_UID) { @@ -2745,8 +2753,8 @@ public class DeviceIdleController extends SystemService } try { int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId); - addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration, - TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, sync, reasonCode, reason); + addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, durationMs, + tempAllowListType, sync, reasonCode, reason); } catch (NameNotFoundException e) { } } @@ -2756,8 +2764,8 @@ public class DeviceIdleController extends SystemService * app an exemption to access network and acquire wakelocks. */ void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid, - long duration, @TempAllowListType int type, boolean sync, @ReasonCode int reasonCode, - @Nullable String reason) { + long duration, @TempAllowListType int tempAllowListType, boolean sync, + @ReasonCode int reasonCode, @Nullable String reason) { final long timeNow = SystemClock.elapsedRealtime(); boolean informWhitelistChanged = false; int appId = UserHandle.getAppId(uid); @@ -2782,8 +2790,8 @@ public class DeviceIdleController extends SystemService } catch (RemoteException e) { } postTempActiveTimeoutMessage(uid, duration); - updateTempWhitelistAppIdsLocked(uid, true, duration, type, reasonCode, - reason, callingUid); + updateTempWhitelistAppIdsLocked(uid, true, duration, tempAllowListType, + reasonCode, reason, callingUid); if (sync) { informWhitelistChanged = true; } else { diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java index dd1a0e2478dd..1a808c9b3c33 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -2042,7 +2042,9 @@ public class AppStandbyController if (activityManager.isLowRamDevice() || ActivityManager.isSmallBatteryDevice()) { mAutoRestrictedBucketDelayMs = 12 * ONE_HOUR; } - + } else if (phase == PHASE_BOOT_COMPLETED) { + // mWellbeingApp needs to be initialized lazily after boot to allow for roles to be + // parsed and the wellbeing role-holder to be assigned final PackageManager packageManager = mContext.getPackageManager(); mWellbeingApp = packageManager.getWellbeingPackageName(); } diff --git a/core/api/current.txt b/core/api/current.txt index 57e256142eb0..6e7d0f4d08f4 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1259,6 +1259,7 @@ package android { field public static final int segmentedButtonStyle = 16843568; // 0x1010330 field public static final int selectAllOnFocus = 16843102; // 0x101015e field public static final int selectable = 16843238; // 0x10101e6 + field public static final int selectableAsDefault = 16844352; // 0x1010640 field public static final int selectableItemBackground = 16843534; // 0x101030e field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c field @Deprecated public static final int selectedDateVerticalBar = 16843591; // 0x1010347 @@ -5818,6 +5819,8 @@ package android.app { method @Nullable public android.graphics.drawable.Icon getIcon(); method @Nullable public android.app.PendingIntent getIntent(); method @Nullable public String getShortcutId(); + method public boolean isBubbleSuppressable(); + method public boolean isBubbleSuppressed(); method public boolean isNotificationSuppressed(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.BubbleMetadata> CREATOR; @@ -5834,6 +5837,7 @@ package android.app { method @NonNull public android.app.Notification.BubbleMetadata.Builder setDesiredHeightResId(@DimenRes int); method @NonNull public android.app.Notification.BubbleMetadata.Builder setIcon(@NonNull android.graphics.drawable.Icon); method @NonNull public android.app.Notification.BubbleMetadata.Builder setIntent(@NonNull android.app.PendingIntent); + method @NonNull public android.app.Notification.BubbleMetadata.Builder setSuppressBubble(boolean); method @NonNull public android.app.Notification.BubbleMetadata.Builder setSuppressNotification(boolean); } @@ -34745,6 +34749,7 @@ package android.provider { field public static final String ACTION_APP_NOTIFICATION_SETTINGS = "android.settings.APP_NOTIFICATION_SETTINGS"; field public static final String ACTION_APP_SEARCH_SETTINGS = "android.settings.APP_SEARCH_SETTINGS"; field public static final String ACTION_APP_USAGE_SETTINGS = "android.settings.action.APP_USAGE_SETTINGS"; + field public static final String ACTION_AUTO_ROTATE_SETTINGS = "android.settings.AUTO_ROTATE_SETTINGS"; field public static final String ACTION_BATTERY_SAVER_SETTINGS = "android.settings.BATTERY_SAVER_SETTINGS"; field public static final String ACTION_BIOMETRIC_ENROLL = "android.settings.BIOMETRIC_ENROLL"; field public static final String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS"; diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 8df783701b0d..67c8b7255c67 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -247,6 +247,7 @@ package android { field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION"; field public static final String SERIAL_PORT = "android.permission.SERIAL_PORT"; field public static final String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER"; + field public static final String SET_CLIP_SOURCE = "android.permission.SET_CLIP_SOURCE"; field public static final String SET_HARMFUL_APP_WARNINGS = "android.permission.SET_HARMFUL_APP_WARNINGS"; field public static final String SET_MEDIA_KEY_LISTENER = "android.permission.SET_MEDIA_KEY_LISTENER"; field public static final String SET_ORIENTATION = "android.permission.SET_ORIENTATION"; @@ -359,6 +360,7 @@ package android { field public static final int config_systemGallery = 17039399; // 0x1040027 field public static final int config_systemShell = 17039402; // 0x104002a field public static final int config_systemSpeechRecognizer = 17039406; // 0x104002e + field public static final int config_systemWellbeing = 17039408; // 0x1040030 field public static final int config_systemWifiCoexManager = 17039407; // 0x104002f } @@ -2119,6 +2121,10 @@ package android.content { method @NonNull public final android.os.UserHandle getSendingUser(); } + public class ClipboardManager extends android.text.ClipboardManager { + method @RequiresPermission(android.Manifest.permission.SET_CLIP_SOURCE) public void setPrimaryClipAsPackage(@NonNull android.content.ClipData, @NonNull String); + } + public abstract class ContentProvider implements android.content.ComponentCallbacks2 { method public int checkUriPermission(@NonNull android.net.Uri, int, int); } @@ -2698,7 +2704,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000 field public static final int PROTECTION_FLAG_ROLE = 67108864; // 0x4000000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 - field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 + field @Deprecated public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 field @Nullable public final String backgroundPermission; field @StringRes public int requestRes; } @@ -4338,7 +4344,7 @@ package android.location { public final class CorrelationVector implements android.os.Parcelable { method public int describeContents(); - method @IntRange(from=0) public int getFrequencyOffsetMetersPerSecond(); + method @FloatRange(from=0.0f) public double getFrequencyOffsetMetersPerSecond(); method @NonNull public int[] getMagnitude(); method @FloatRange(from=0.0f) public double getSamplingStartMeters(); method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters(); @@ -4349,7 +4355,7 @@ package android.location { public static final class CorrelationVector.Builder { ctor public CorrelationVector.Builder(); method @NonNull public android.location.CorrelationVector build(); - method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@IntRange(from=0) int); + method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@FloatRange(from=0.0f) double); method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]); method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double); method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double); @@ -12995,7 +13001,7 @@ package android.telephony.ims { method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException; - method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); @@ -13003,7 +13009,7 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); - method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback); field @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE = "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE"; field public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS"; field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.ims.extra.SUBSCRIPTION_ID"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index b7e294aed6b5..75b9525b110c 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -658,6 +658,10 @@ package android.content { field @Nullable public android.util.ArraySet<android.content.ComponentName> whitelistedActivitiesForAugmentedAutofill; } + public class ClipboardManager extends android.text.ClipboardManager { + method @Nullable @RequiresPermission(android.Manifest.permission.SET_CLIP_SOURCE) public String getPrimaryClipSource(); + } + public final class ContentCaptureOptions implements android.os.Parcelable { ctor public ContentCaptureOptions(int); ctor public ContentCaptureOptions(int, int, int, int, int, @Nullable android.util.ArraySet<android.content.ComponentName>); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 4ebed7a6cf43..b00cfcb0d020 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -6254,6 +6254,9 @@ public class Notification implements Parcelable if (rawColor == COLOR_DEFAULT) { ensureColors(p); color = ContrastColorUtil.resolveDefaultColor(mContext, background, mInNightMode); + if (mTintWithThemeAccent) { + color = obtainThemeColor(R.attr.colorAccent, color); + } } else { color = ContrastColorUtil.resolveContrastColor(mContext, rawColor, background, mInNightMode); @@ -9904,6 +9907,22 @@ public class Notification implements Parcelable */ public static final int FLAG_SUPPRESS_NOTIFICATION = 0x00000002; + /** + * Indicates whether the bubble should be visually suppressed from the bubble stack if the + * user is viewing the same content outside of the bubble. For example, the user has a + * bubble with Alice and then opens up the main app and navigates to Alice's page. + * + * @hide + */ + public static final int FLAG_SHOULD_SUPPRESS_BUBBLE = 0x00000004; + + /** + * Indicates whether the bubble is visually suppressed from the bubble stack. + * + * @hide + */ + public static final int FLAG_SUPPRESS_BUBBLE = 0x00000008; + private BubbleMetadata(PendingIntent expandIntent, PendingIntent deleteIntent, Icon icon, int height, @DimenRes int heightResId, String shortcutId) { mPendingIntent = expandIntent; @@ -10046,6 +10065,32 @@ public class Notification implements Parcelable return (mFlags & FLAG_SUPPRESS_NOTIFICATION) != 0; } + /** + * Indicates whether the bubble should be visually suppressed from the bubble stack if the + * user is viewing the same content outside of the bubble. For example, the user has a + * bubble with Alice and then opens up the main app and navigates to Alice's page. + * + * To match the activity and the bubble notification, the bubble notification should + * have a locus id set that matches a locus id set on the activity. + * + * @return whether this bubble should be suppressed when the same content is visible + * outside of the bubble. + * + * @see BubbleMetadata.Builder#setSuppressBubble(boolean) + */ + public boolean isBubbleSuppressable() { + return (mFlags & FLAG_SHOULD_SUPPRESS_BUBBLE) != 0; + } + + /** + * Indicates whether the bubble is currently visually suppressed from the bubble stack. + * + * @see BubbleMetadata.Builder#setSuppressBubble(boolean) + */ + public boolean isBubbleSuppressed() { + return (mFlags & FLAG_SUPPRESS_BUBBLE) != 0; + } + public static final @android.annotation.NonNull Parcelable.Creator<BubbleMetadata> CREATOR = new Parcelable.Creator<BubbleMetadata>() { @@ -10388,6 +10433,23 @@ public class Notification implements Parcelable } /** + * Indicates whether the bubble should be visually suppressed from the bubble stack if + * the user is viewing the same content outside of the bubble. For example, the user has + * a bubble with Alice and then opens up the main app and navigates to Alice's page. + * + * To match the activity and the bubble notification, the bubble notification should + * have a locus id set that matches a locus id set on the activity. + * + * {@link Notification.Builder#setLocusId(LocusId)} + * {@link Activity#setLocusContext(LocusId, Bundle)} + */ + @NonNull + public BubbleMetadata.Builder setSuppressBubble(boolean suppressBubble) { + setFlag(FLAG_SHOULD_SUPPRESS_BUBBLE, suppressBubble); + return this; + } + + /** * Sets an intent to send when this bubble is explicitly removed by the user. * * <p>Setting a delete intent is optional.</p> diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 9019ddf941d9..6ad5eea8b602 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -24,6 +24,7 @@ import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Intent; +import android.content.LocusId; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; @@ -123,6 +124,13 @@ public class TaskInfo { public ActivityManager.TaskDescription taskDescription; /** + * The locusId of the task. + * @hide + */ + @Nullable + public LocusId mTopActivityLocusId; + + /** * True if the task can go in the split-screen primary stack. * @hide */ @@ -381,6 +389,7 @@ public class TaskInfo { isVisible = source.readBoolean(); topActivityToken = source.readStrongBinder(); topActivityInSizeCompat = source.readBoolean(); + mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR); } /** @@ -417,6 +426,7 @@ public class TaskInfo { dest.writeBoolean(isVisible); dest.writeStrongBinder(topActivityToken); dest.writeBoolean(topActivityInSizeCompat); + dest.writeTypedObject(mTopActivityLocusId, flags); } @Override @@ -443,6 +453,7 @@ public class TaskInfo { + " isVisible=" + isVisible + " topActivityToken=" + topActivityToken + " topActivityInSizeCompat=" + topActivityInSizeCompat + + " locusId= " + mTopActivityLocusId + "}"; } } diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java index 0a8a73404a7b..6b2e649b0c69 100644 --- a/core/java/android/app/WallpaperColors.java +++ b/core/java/android/app/WallpaperColors.java @@ -32,6 +32,7 @@ import android.util.Size; import com.android.internal.graphics.ColorUtils; import com.android.internal.graphics.palette.CelebiQuantizer; import com.android.internal.graphics.palette.Palette; +import com.android.internal.graphics.palette.VariationalKMeansQuantizer; import com.android.internal.util.ContrastColorUtil; import java.io.FileOutputStream; @@ -178,11 +179,20 @@ public final class WallpaperColors implements Parcelable { optimalSize.getHeight(), true /* filter */); } - final Palette palette = Palette - .from(bitmap, new CelebiQuantizer()) - .maximumColorCount(256) - .resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA) - .generate(); + final Palette palette; + if (ActivityManager.isLowRamDeviceStatic()) { + palette = Palette + .from(bitmap, new VariationalKMeansQuantizer()) + .maximumColorCount(5) + .resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA) + .generate(); + } else { + palette = Palette + .from(bitmap, new CelebiQuantizer()) + .maximumColorCount(256) + .resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA) + .generate(); + } // Remove insignificant colors and sort swatches by population final ArrayList<Palette.Swatch> swatches = new ArrayList<>(palette.getSwatches()); swatches.sort((a, b) -> b.getPopulation() - a.getPopulation()); diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java index 7f73238a41e3..cadbd609ff0b 100644 --- a/core/java/android/content/ClipboardManager.java +++ b/core/java/android/content/ClipboardManager.java @@ -16,9 +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.annotation.SystemService; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Handler; import android.os.RemoteException; @@ -109,6 +113,31 @@ public class ClipboardManager extends android.text.ClipboardManager { } /** + * Sets the current primary clip on the clipboard, attributed to the specified {@code + * sourcePackage}. The primary clip is the clip that is involved in normal cut and paste + * operations. + * + * @param clip The clipped data item to set. + * @param sourcePackage The package name of the app that is the source of the clip data. + * @throws IllegalArgumentException if the clip is null or contains no items. + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.SET_CLIP_SOURCE) + public void setPrimaryClipAsPackage(@NonNull ClipData clip, @NonNull String sourcePackage) { + try { + Objects.requireNonNull(clip); + Objects.requireNonNull(sourcePackage); + clip.prepareToLeaveProcess(true); + mService.setPrimaryClipAsPackage( + clip, mContext.getOpPackageName(), mContext.getUserId(), sourcePackage); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Clears any current primary clip on the clipboard. * * @see #setPrimaryClip(ClipData) @@ -234,6 +263,23 @@ public class ClipboardManager extends android.text.ClipboardManager { } } + /** + * Returns the package name of the source of the current primary clip, or null if there is no + * primary clip or if a source is not available. + * + * @hide + */ + @TestApi + @Nullable + @RequiresPermission(Manifest.permission.SET_CLIP_SOURCE) + public String getPrimaryClipSource() { + try { + return mService.getPrimaryClipSource(mContext.getOpPackageName(), mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + @UnsupportedAppUsage void reportPrimaryClipChanged() { Object[] listeners; diff --git a/core/java/android/content/IClipboard.aidl b/core/java/android/content/IClipboard.aidl index 0d5a46016f19..102b8e798a5c 100644 --- a/core/java/android/content/IClipboard.aidl +++ b/core/java/android/content/IClipboard.aidl @@ -27,6 +27,8 @@ import android.content.IOnPrimaryClipChangedListener; */ interface IClipboard { void setPrimaryClip(in ClipData clip, String callingPackage, int userId); + void setPrimaryClipAsPackage(in ClipData clip, String callingPackage, int userId, + String sourcePackage); void clearPrimaryClip(String callingPackage, int userId); ClipData getPrimaryClip(String pkg, int userId); ClipDescription getPrimaryClipDescription(String callingPackage, int userId); @@ -40,4 +42,6 @@ interface IClipboard { * Returns true if the clipboard contains text; false otherwise. */ boolean hasClipboardText(String callingPackage, int userId); + + String getPrimaryClipSource(String callingPackage, int userId); } diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index 83baca668d55..691c69c2459a 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -200,6 +200,8 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { * to the <code>wellbeing</code> value of * {@link android.R.attr#protectionLevel}. * + * @deprecated this protectionLevel is obsolete. Permissions previously granted through this + * protectionLevel have been migrated to use <code>role</code> instead * @hide */ @SystemApi @@ -307,7 +309,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { PROTECTION_FLAG_OEM, PROTECTION_FLAG_VENDOR_PRIVILEGED, PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER, - PROTECTION_FLAG_WELLBEING, PROTECTION_FLAG_DOCUMENTER, PROTECTION_FLAG_CONFIGURATOR, PROTECTION_FLAG_INCIDENT_REPORT_APPROVER, @@ -560,9 +561,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0) { protLevel.append("|textClassifier"); } - if ((level & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0) { - protLevel.append("|wellbeing"); - } if ((level & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0) { protLevel.append("|documenter"); } diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING index 953400e10e15..8bc3734e060d 100644 --- a/core/java/android/content/pm/TEST_MAPPING +++ b/core/java/android/content/pm/TEST_MAPPING @@ -31,6 +31,14 @@ "include-filter": "android.content.pm.cts" } ] + }, + { + "name": "CtsIncrementalInstallHostTestCases", + "options": [ + { + "include-filter": "android.incrementalinstall.cts.IncrementalFeatureTest" + } + ] } ], "postsubmit": [ diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java index de48ed75746d..f3783e4a1328 100644 --- a/core/java/android/content/res/ApkAssets.java +++ b/core/java/android/content/res/ApkAssets.java @@ -26,8 +26,6 @@ import android.text.TextUtils; import com.android.internal.annotations.GuardedBy; -import libcore.util.NativeAllocationRegistry; - import java.io.FileDescriptor; import java.io.IOException; import java.lang.annotation.Retention; @@ -104,11 +102,11 @@ public final class ApkAssets { public @interface FormatType {} @GuardedBy("this") - private final long mNativePtr; + private long mNativePtr; // final, except cleared in finalizer. @Nullable @GuardedBy("this") - private final StringBlock mStringBlock; + private final StringBlock mStringBlock; // null or closed if mNativePtr = 0. @PropertyFlags private final int mFlags; @@ -116,19 +114,6 @@ public final class ApkAssets { @Nullable private final AssetsProvider mAssets; - @GuardedBy("this") - @Nullable - private final Runnable mRunNativeCleanup; - - // Use a Holder to allow static initialization of ApkAssets in the boot image, and - // possibly to avoid some initialization ordering issues. - private static class NoImagePreloadHolder { - // TODO(175425996): Make size estimate more accurate - public static final NativeAllocationRegistry REGISTRY = - NativeAllocationRegistry.createMalloced(ApkAssets.class.getClassLoader(), - nativeGetFinalizer()); - } - /** * Creates a new ApkAssets instance from the given path on disk. * @@ -303,8 +288,6 @@ public final class ApkAssets { mFlags = flags; mNativePtr = nativeLoad(format, path, flags, assets); mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/); - mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation( - this, mNativePtr); mAssets = assets; } @@ -316,8 +299,6 @@ public final class ApkAssets { mFlags = flags; mNativePtr = nativeLoadFd(format, fd, friendlyName, flags, assets); mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/); - mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation( - this, mNativePtr); mAssets = assets; } @@ -329,8 +310,6 @@ public final class ApkAssets { mFlags = flags; mNativePtr = nativeLoadFdOffsets(format, fd, friendlyName, offset, length, flags, assets); mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/); - mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation( - this, mNativePtr); mAssets = assets; } @@ -338,7 +317,6 @@ public final class ApkAssets { mFlags = flags; mNativePtr = nativeLoadEmpty(flags, assets); mStringBlock = null; - mRunNativeCleanup = null; mAssets = assets; } @@ -433,16 +411,22 @@ public final class ApkAssets { return "ApkAssets{path=" + getDebugName() + "}"; } + @Override + protected void finalize() throws Throwable { + close(); + } + /** * Closes this class and the contained {@link #mStringBlock}. */ public void close() { synchronized (this) { - if (mStringBlock != null) { - mStringBlock.close(); - } - if (mRunNativeCleanup != null) { - mRunNativeCleanup.run(); + if (mNativePtr != 0) { + if (mStringBlock != null) { + mStringBlock.close(); + } + nativeDestroy(mNativePtr); + mNativePtr = 0; } } } @@ -457,6 +441,7 @@ public final class ApkAssets { private static native long nativeLoadFdOffsets(@FormatType int format, @NonNull FileDescriptor fd, @NonNull String friendlyName, long offset, long length, @PropertyFlags int flags, @Nullable AssetsProvider asset) throws IOException; + private static native void nativeDestroy(long ptr); private static native @NonNull String nativeGetAssetPath(long ptr); private static native @NonNull String nativeGetDebugName(long ptr); private static native long nativeGetStringBlock(long ptr); @@ -465,5 +450,4 @@ public final class ApkAssets { private static native @Nullable OverlayableInfo nativeGetOverlayableInfo(long ptr, String overlayableName) throws IOException; private static native boolean nativeDefinesOverlayable(long ptr) throws IOException; - private static native final long nativeGetFinalizer(); } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 6901df7508ab..66f7bd9d8dee 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -986,26 +986,26 @@ public abstract class BatteryStats implements Parcelable { public abstract void getDeferredJobsLineLocked(StringBuilder sb, int which); /** - * Returns the measured energy in microjoules that the display consumed while the screen - * was on and uid active. - * Will return {@link #ENERGY_DATA_UNAVAILABLE} if data is unavailable + * Returns the battery consumption (in microcoulombs) of the screen while on and uid active, + * derived from on device power measurement data. + * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ - public abstract long getScreenOnEnergy(); + public abstract long getScreenOnMeasuredBatteryConsumptionUC(); /** - * Returns the energies used by this uid for each + * Returns the battery consumption (in microcoulombs) used by this uid for each * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}). * - * @return energies (in microjoules) used since boot for each (custom) energy consumer of - * type OTHER, indexed by their ordinal. Returns null if no energy reporting is - * supported. + * @return charge (in microcoulombs) consumed since last reset for each (custom) energy + * consumer of type OTHER, indexed by their ordinal. Returns null if no energy + * reporting is supported. * * {@hide} */ - public abstract @Nullable long[] getCustomMeasuredEnergiesMicroJoules(); + public abstract @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC(); public static abstract class Sensor { @@ -2496,40 +2496,41 @@ public abstract class BatteryStats implements Parcelable { }; /** - * Returned value if energy data is unavailable + * Returned value if power data is unavailable * * {@hide} */ - public static final long ENERGY_DATA_UNAVAILABLE = -1; + public static final long POWER_DATA_UNAVAILABLE = -1; /** - * Returns the energy in microjoules that the screen consumed while on. - * Will return {@link #ENERGY_DATA_UNAVAILABLE} if data is unavailable + * Returns the battery consumption (in microcoulombs) of the screen while on, derived from on + * device power measurement data. + * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ - public abstract long getScreenOnEnergy(); + public abstract long getScreenOnMeasuredBatteryConsumptionUC(); /** - * Returns the energy in microjoules that the screen consumed while in doze - * Will return {@link #ENERGY_DATA_UNAVAILABLE} if data is unavailable + * Returns the battery consumption (in microcoulombs) of the screen in doze, derived from on + * device power measurement data. + * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ - public abstract long getScreenDozeEnergy(); + public abstract long getScreenDozeMeasuredBatteryConsumptionUC(); /** - * Returns the energies used for each + * Returns the battery consumption (in microcoulombs) that each * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer - * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}). + * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}) consumed. * - * @return energies (in microjoules) used since boot for each (custom) energy consumer of - * type OTHER, indexed by their ordinal. Returns null if no energy reporting is - * supported. + * @return charge (in microcoulombs) used by each (custom) energy consumer of type OTHER, + * indexed by their ordinal. Returns null if no energy reporting is supported. * * {@hide} */ - public abstract @Nullable long[] getCustomMeasuredEnergiesMicroJoules(); + public abstract @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC(); public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS = new BitDescription[] { new BitDescription(HistoryItem.STATE_CPU_RUNNING_FLAG, "running", "r"), diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 85cef84d8d30..4dfbb6fa2d05 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -825,6 +825,13 @@ public final class Settings { "android.settings.DISPLAY_SETTINGS"; /** + * Activity Action: Show Auto Rotate configuration settings. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_AUTO_ROTATE_SETTINGS = + "android.settings.AUTO_ROTATE_SETTINGS"; + + /** * Activity Action: Show settings to allow configuration of Night display. * <p> * In some cases, a matching Activity may not exist, so ensure you diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index e5a137cd13f3..09452828057e 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -86,12 +86,6 @@ public final class AccessibilityInteractionController { // accessibility from hanging private static final long REQUEST_PREPARER_TIMEOUT_MS = 500; - // Callbacks should have the same configuration of the flags below to allow satisfying a pending - // node request on prefetch - private static final int FLAGS_AFFECTING_REPORTED_DATA = - AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS - | AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; - private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList = new ArrayList<AccessibilityNodeInfo>(); @@ -120,9 +114,6 @@ public final class AccessibilityInteractionController { private AddNodeInfosForViewId mAddNodeInfosForViewId; @GuardedBy("mLock") - private ArrayList<Message> mPendingFindNodeByIdMessages; - - @GuardedBy("mLock") private int mNumActiveRequestPreparers; @GuardedBy("mLock") private List<MessageHolder> mMessagesWaitingForRequestPreparer; @@ -137,7 +128,6 @@ public final class AccessibilityInteractionController { mViewRootImpl = viewRootImpl; mPrefetcher = new AccessibilityNodePrefetcher(); mA11yManager = mViewRootImpl.mContext.getSystemService(AccessibilityManager.class); - mPendingFindNodeByIdMessages = new ArrayList<>(); } private void scheduleMessage(Message message, int interrogatingPid, long interrogatingTid, @@ -187,11 +177,7 @@ public final class AccessibilityInteractionController { args.arg4 = arguments; message.obj = args; - synchronized (mLock) { - mPendingFindNodeByIdMessages.add(message); - scheduleMessage(message, interrogatingPid, interrogatingTid, - CONSIDER_REQUEST_PREPARERS); - } + scheduleMessage(message, interrogatingPid, interrogatingTid, CONSIDER_REQUEST_PREPARERS); } /** @@ -329,9 +315,6 @@ public final class AccessibilityInteractionController { } private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) { - synchronized (mLock) { - mPendingFindNodeByIdMessages.remove(message); - } final int flags = message.arg1; SomeArgs args = (SomeArgs) message.obj; @@ -346,58 +329,22 @@ public final class AccessibilityInteractionController { args.recycle(); - View rootView = null; - AccessibilityNodeInfo rootNode = null; + List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList; + infos.clear(); try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - rootView = findViewByAccessibilityId(accessibilityViewId); - if (rootView != null && isShown(rootView)) { - rootNode = populateAccessibilityNodeInfoForView( - rootView, arguments, virtualDescendantId); + final View root = findViewByAccessibilityId(accessibilityViewId); + if (root != null && isShown(root)) { + mPrefetcher.prefetchAccessibilityNodeInfos( + root, virtualDescendantId, flags, infos, arguments); } } finally { - updateInfoForViewportAndReturnFindNodeResult( - rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode), - callback, interactionId, spec, interactiveRegion); - } - ArrayList<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList; - infos.clear(); - mPrefetcher.prefetchAccessibilityNodeInfos( - rootView, rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode), - virtualDescendantId, flags, infos); - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - updateInfosForViewPort(infos, spec, interactiveRegion); - returnPrefetchResult(interactionId, infos, callback); - returnPendingFindAccessibilityNodeInfosInPrefetch(rootNode, infos, flags); - } - - private AccessibilityNodeInfo populateAccessibilityNodeInfoForView( - View view, Bundle arguments, int virtualViewId) { - AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider(); - // Determine if we'll be populating extra data - final String extraDataRequested = (arguments == null) ? null - : arguments.getString(EXTRA_DATA_REQUESTED_KEY); - AccessibilityNodeInfo root = null; - if (provider == null) { - root = view.createAccessibilityNodeInfo(); - if (root != null) { - if (extraDataRequested != null) { - view.addExtraDataToAccessibilityNodeInfo(root, extraDataRequested, arguments); - } - } - } else { - root = provider.createAccessibilityNodeInfo(virtualViewId); - if (root != null) { - if (extraDataRequested != null) { - provider.addExtraDataToAccessibilityNodeInfo( - virtualViewId, root, extraDataRequested, arguments); - } - } + updateInfosForViewportAndReturnFindNodeResult( + infos, callback, interactionId, spec, interactiveRegion); } - return root; } public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId, @@ -456,7 +403,6 @@ public final class AccessibilityInteractionController { mAddNodeInfosForViewId.reset(); } } finally { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfosForViewportAndReturnFindNodeResult( infos, callback, interactionId, spec, interactiveRegion); } @@ -539,7 +485,6 @@ public final class AccessibilityInteractionController { } } } finally { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfosForViewportAndReturnFindNodeResult( infos, callback, interactionId, spec, interactiveRegion); } @@ -631,7 +576,6 @@ public final class AccessibilityInteractionController { } } } finally { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfoForViewportAndReturnFindNodeResult( focused, callback, interactionId, spec, interactiveRegion); } @@ -686,7 +630,6 @@ public final class AccessibilityInteractionController { } } } finally { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfoForViewportAndReturnFindNodeResult( next, callback, interactionId, spec, interactiveRegion); } @@ -843,6 +786,33 @@ public final class AccessibilityInteractionController { } } + private void applyAppScaleAndMagnificationSpecIfNeeded(List<AccessibilityNodeInfo> infos, + MagnificationSpec spec) { + if (infos == null) { + return; + } + final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale; + if (shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) { + final int infoCount = infos.size(); + for (int i = 0; i < infoCount; i++) { + AccessibilityNodeInfo info = infos.get(i); + applyAppScaleAndMagnificationSpecIfNeeded(info, spec); + } + } + } + + private void adjustIsVisibleToUserIfNeeded(List<AccessibilityNodeInfo> infos, + Region interactiveRegion) { + if (interactiveRegion == null || infos == null) { + return; + } + final int infoCount = infos.size(); + for (int i = 0; i < infoCount; i++) { + AccessibilityNodeInfo info = infos.get(i); + adjustIsVisibleToUserIfNeeded(info, interactiveRegion); + } + } + private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info, Region interactiveRegion) { if (interactiveRegion == null || info == null) { @@ -863,6 +833,17 @@ public final class AccessibilityInteractionController { return false; } + private void adjustBoundsInScreenIfNeeded(List<AccessibilityNodeInfo> infos) { + if (infos == null || shouldBypassAdjustBoundsInScreen()) { + return; + } + final int infoCount = infos.size(); + for (int i = 0; i < infoCount; i++) { + final AccessibilityNodeInfo info = infos.get(i); + adjustBoundsInScreenIfNeeded(info); + } + } + private void adjustBoundsInScreenIfNeeded(AccessibilityNodeInfo info) { if (info == null || shouldBypassAdjustBoundsInScreen()) { return; @@ -910,6 +891,17 @@ public final class AccessibilityInteractionController { return screenMatrix == null || screenMatrix.isIdentity(); } + private void associateLeashedParentIfNeeded(List<AccessibilityNodeInfo> infos) { + if (infos == null || shouldBypassAssociateLeashedParent()) { + return; + } + final int infoCount = infos.size(); + for (int i = 0; i < infoCount; i++) { + final AccessibilityNodeInfo info = infos.get(i); + associateLeashedParentIfNeeded(info); + } + } + private void associateLeashedParentIfNeeded(AccessibilityNodeInfo info) { if (info == null || shouldBypassAssociateLeashedParent()) { return; @@ -983,46 +975,18 @@ public final class AccessibilityInteractionController { return (appScale != 1.0f || (spec != null && !spec.isNop())); } - private void updateInfosForViewPort(List<AccessibilityNodeInfo> infos, MagnificationSpec spec, - Region interactiveRegion) { - for (int i = 0; i < infos.size(); i++) { - updateInfoForViewPort(infos.get(i), spec, interactiveRegion); - } - } - - private void updateInfoForViewPort(AccessibilityNodeInfo info, MagnificationSpec spec, - Region interactiveRegion) { - associateLeashedParentIfNeeded(info); - applyScreenMatrixIfNeeded(info); - adjustBoundsInScreenIfNeeded(info); - // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node, - // then impact the visibility result, we need to adjust visibility before apply scale. - adjustIsVisibleToUserIfNeeded(info, interactiveRegion); - applyAppScaleAndMagnificationSpecIfNeeded(info, spec); - } - private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos, IAccessibilityInteractionConnectionCallback callback, int interactionId, MagnificationSpec spec, Region interactiveRegion) { - if (infos != null) { - updateInfosForViewPort(infos, spec, interactiveRegion); - } - returnFindNodesResult(infos, callback, interactionId); - } - - private void returnFindNodeResult(AccessibilityNodeInfo info, - IAccessibilityInteractionConnectionCallback callback, - int interactionId) { - try { - callback.setFindAccessibilityNodeInfoResult(info, interactionId); - } catch (RemoteException re) { - /* ignore - the other side will time out */ - } - } - - private void returnFindNodesResult(List<AccessibilityNodeInfo> infos, - IAccessibilityInteractionConnectionCallback callback, int interactionId) { try { + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; + associateLeashedParentIfNeeded(infos); + applyScreenMatrixIfNeeded(infos); + adjustBoundsInScreenIfNeeded(infos); + // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node, + // then impact the visibility result, we need to adjust visibility before apply scale. + adjustIsVisibleToUserIfNeeded(infos, interactiveRegion); + applyAppScaleAndMagnificationSpecIfNeeded(infos, spec); callback.setFindAccessibilityNodeInfosResult(infos, interactionId); if (infos != null) { infos.clear(); @@ -1032,80 +996,22 @@ public final class AccessibilityInteractionController { } } - private void returnPendingFindAccessibilityNodeInfosInPrefetch(AccessibilityNodeInfo rootNode, - List<AccessibilityNodeInfo> infos, int flags) { - - AccessibilityNodeInfo satisfiedPendingRequestPrefetchedNode = null; - IAccessibilityInteractionConnectionCallback satisfiedPendingRequestCallback = null; - int satisfiedPendingRequestInteractionId = AccessibilityInteractionClient.NO_ID; - - synchronized (mLock) { - for (int i = 0; i < mPendingFindNodeByIdMessages.size(); i++) { - final Message pendingMessage = mPendingFindNodeByIdMessages.get(i); - final int pendingFlags = pendingMessage.arg1; - if ((pendingFlags & FLAGS_AFFECTING_REPORTED_DATA) - != (flags & FLAGS_AFFECTING_REPORTED_DATA)) { - continue; - } - SomeArgs args = (SomeArgs) pendingMessage.obj; - final int accessibilityViewId = args.argi1; - final int virtualDescendantId = args.argi2; - - satisfiedPendingRequestPrefetchedNode = nodeWithIdFromList(rootNode, - infos, AccessibilityNodeInfo.makeNodeId( - accessibilityViewId, virtualDescendantId)); - - if (satisfiedPendingRequestPrefetchedNode != null) { - satisfiedPendingRequestCallback = - (IAccessibilityInteractionConnectionCallback) args.arg1; - satisfiedPendingRequestInteractionId = args.argi3; - mHandler.removeMessages( - PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID, - pendingMessage.obj); - args.recycle(); - break; - } - } - mPendingFindNodeByIdMessages.clear(); - } - - if (satisfiedPendingRequestPrefetchedNode != null) { - returnFindNodeResult( - AccessibilityNodeInfo.obtain(satisfiedPendingRequestPrefetchedNode), - satisfiedPendingRequestCallback, satisfiedPendingRequestInteractionId); - } - } - - private AccessibilityNodeInfo nodeWithIdFromList(AccessibilityNodeInfo rootNode, - List<AccessibilityNodeInfo> infos, long nodeId) { - if (rootNode != null && rootNode.getSourceNodeId() == nodeId) { - return rootNode; - } - for (int j = 0; j < infos.size(); j++) { - AccessibilityNodeInfo info = infos.get(j); - if (info.getSourceNodeId() == nodeId) { - return info; - } - } - return null; - } - - private void returnPrefetchResult(int interactionId, List<AccessibilityNodeInfo> infos, - IAccessibilityInteractionConnectionCallback callback) { - if (infos.size() > 0) { - try { - callback.setPrefetchAccessibilityNodeInfoResult(infos, interactionId); - } catch (RemoteException re) { - /* ignore - other side isn't too bothered if this doesn't arrive */ - } - } - } - private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info, IAccessibilityInteractionConnectionCallback callback, int interactionId, MagnificationSpec spec, Region interactiveRegion) { - updateInfoForViewPort(info, spec, interactiveRegion); - returnFindNodeResult(info, callback, interactionId); + try { + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; + associateLeashedParentIfNeeded(info); + applyScreenMatrixIfNeeded(info); + adjustBoundsInScreenIfNeeded(info); + // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node, + // then impact the visibility result, we need to adjust visibility before apply scale. + adjustIsVisibleToUserIfNeeded(info, interactiveRegion); + applyAppScaleAndMagnificationSpecIfNeeded(info, spec); + callback.setFindAccessibilityNodeInfoResult(info, interactionId); + } catch (RemoteException re) { + /* ignore - the other side will time out */ + } } private boolean handleClickableSpanActionUiThread( @@ -1148,45 +1054,56 @@ public final class AccessibilityInteractionController { private final ArrayList<View> mTempViewList = new ArrayList<View>(); - public void prefetchAccessibilityNodeInfos(View view, AccessibilityNodeInfo root, - int virtualViewId, int fetchFlags, List<AccessibilityNodeInfo> outInfos) { - if (root == null) { - return; - } + public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int fetchFlags, + List<AccessibilityNodeInfo> outInfos, Bundle arguments) { AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider(); + // Determine if we'll be populating extra data + final String extraDataRequested = (arguments == null) ? null + : arguments.getString(EXTRA_DATA_REQUESTED_KEY); if (provider == null) { - if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { - prefetchPredecessorsOfRealNode(view, outInfos); - } - if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0) { - prefetchSiblingsOfRealNode(view, outInfos); - } - if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) { - prefetchDescendantsOfRealNode(view, outInfos); + AccessibilityNodeInfo root = view.createAccessibilityNodeInfo(); + if (root != null) { + if (extraDataRequested != null) { + view.addExtraDataToAccessibilityNodeInfo( + root, extraDataRequested, arguments); + } + outInfos.add(root); + if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { + prefetchPredecessorsOfRealNode(view, outInfos); + } + if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0) { + prefetchSiblingsOfRealNode(view, outInfos); + } + if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) { + prefetchDescendantsOfRealNode(view, outInfos); + } } } else { - if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { - prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos); - } - if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0) { - prefetchSiblingsOfVirtualNode(root, view, provider, outInfos); - } - if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) { - prefetchDescendantsOfVirtualNode(root, provider, outInfos); + final AccessibilityNodeInfo root = + provider.createAccessibilityNodeInfo(virtualViewId); + if (root != null) { + if (extraDataRequested != null) { + provider.addExtraDataToAccessibilityNodeInfo( + virtualViewId, root, extraDataRequested, arguments); + } + outInfos.add(root); + if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { + prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos); + } + if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0) { + prefetchSiblingsOfVirtualNode(root, view, provider, outInfos); + } + if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) { + prefetchDescendantsOfVirtualNode(root, provider, outInfos); + } } } if (ENFORCE_NODE_TREE_CONSISTENT) { - enforceNodeTreeConsistent(root, outInfos); + enforceNodeTreeConsistent(outInfos); } } - private boolean shouldStopPrefetching(List prefetchededInfos) { - return mHandler.hasUserInteractiveMessagesWaiting() - || prefetchededInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE; - } - - private void enforceNodeTreeConsistent( - AccessibilityNodeInfo root, List<AccessibilityNodeInfo> nodes) { + private void enforceNodeTreeConsistent(List<AccessibilityNodeInfo> nodes) { LongSparseArray<AccessibilityNodeInfo> nodeMap = new LongSparseArray<AccessibilityNodeInfo>(); final int nodeCount = nodes.size(); @@ -1197,6 +1114,7 @@ public final class AccessibilityInteractionController { // If the nodes are a tree it does not matter from // which node we start to search for the root. + AccessibilityNodeInfo root = nodeMap.valueAt(0); AccessibilityNodeInfo parent = root; while (parent != null) { root = parent; @@ -1263,11 +1181,9 @@ public final class AccessibilityInteractionController { private void prefetchPredecessorsOfRealNode(View view, List<AccessibilityNodeInfo> outInfos) { - if (shouldStopPrefetching(outInfos)) { - return; - } ViewParent parent = view.getParentForAccessibility(); - while (parent instanceof View && !shouldStopPrefetching(outInfos)) { + while (parent instanceof View + && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { View parentView = (View) parent; AccessibilityNodeInfo info = parentView.createAccessibilityNodeInfo(); if (info != null) { @@ -1279,9 +1195,6 @@ public final class AccessibilityInteractionController { private void prefetchSiblingsOfRealNode(View current, List<AccessibilityNodeInfo> outInfos) { - if (shouldStopPrefetching(outInfos)) { - return; - } ViewParent parent = current.getParentForAccessibility(); if (parent instanceof ViewGroup) { ViewGroup parentGroup = (ViewGroup) parent; @@ -1291,7 +1204,7 @@ public final class AccessibilityInteractionController { parentGroup.addChildrenForAccessibility(children); final int childCount = children.size(); for (int i = 0; i < childCount; i++) { - if (shouldStopPrefetching(outInfos)) { + if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { return; } View child = children.get(i); @@ -1319,7 +1232,7 @@ public final class AccessibilityInteractionController { private void prefetchDescendantsOfRealNode(View root, List<AccessibilityNodeInfo> outInfos) { - if (shouldStopPrefetching(outInfos) || !(root instanceof ViewGroup)) { + if (!(root instanceof ViewGroup)) { return; } HashMap<View, AccessibilityNodeInfo> addedChildren = @@ -1330,7 +1243,7 @@ public final class AccessibilityInteractionController { root.addChildrenForAccessibility(children); final int childCount = children.size(); for (int i = 0; i < childCount; i++) { - if (shouldStopPrefetching(outInfos)) { + if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { return; } View child = children.get(i); @@ -1355,7 +1268,7 @@ public final class AccessibilityInteractionController { } finally { children.clear(); } - if (!shouldStopPrefetching(outInfos)) { + if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) { View addedChild = entry.getKey(); AccessibilityNodeInfo virtualRoot = entry.getValue(); @@ -1377,7 +1290,7 @@ public final class AccessibilityInteractionController { long parentNodeId = root.getParentNodeId(); int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId); while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { - if (shouldStopPrefetching(outInfos)) { + if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { return; } final int virtualDescendantId = @@ -1422,7 +1335,7 @@ public final class AccessibilityInteractionController { if (parent != null) { final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { - if (shouldStopPrefetching(outInfos)) { + if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { return; } final long childNodeId = parent.getChildId(i); @@ -1447,7 +1360,7 @@ public final class AccessibilityInteractionController { final int initialOutInfosSize = outInfos.size(); final int childCount = root.getChildCount(); for (int i = 0; i < childCount; i++) { - if (shouldStopPrefetching(outInfos)) { + if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { return; } final long childNodeId = root.getChildId(i); @@ -1457,7 +1370,7 @@ public final class AccessibilityInteractionController { outInfos.add(child); } } - if (!shouldStopPrefetching(outInfos)) { + if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { final int addedChildCount = outInfos.size() - initialOutInfosSize; for (int i = 0; i < addedChildCount; i++) { AccessibilityNodeInfo child = outInfos.get(initialOutInfosSize + i); @@ -1566,10 +1479,6 @@ public final class AccessibilityInteractionController { boolean hasAccessibilityCallback(Message message) { return message.what < FIRST_NO_ACCESSIBILITY_CALLBACK_MSG ? true : false; } - - boolean hasUserInteractiveMessagesWaiting() { - return hasMessagesOrCallbacks(); - } } private final class AddNodeInfosForViewId implements Predicate<View> { diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java index 41bc9a742752..35d95be0b57b 100644 --- a/core/java/android/view/FrameMetricsObserver.java +++ b/core/java/android/view/FrameMetricsObserver.java @@ -45,7 +45,8 @@ public class FrameMetricsObserver mWindow = new WeakReference<>(window); mListener = listener; mFrameMetrics = new FrameMetrics(); - mObserver = new HardwareRendererObserver(this, mFrameMetrics.mTimingData, handler); + mObserver = new HardwareRendererObserver(this, mFrameMetrics.mTimingData, handler, + false /*waitForPresentTime*/); } /** diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java index 7d1adc36964b..79d8c14aa0df 100644 --- a/core/java/android/view/InputEventReceiver.java +++ b/core/java/android/view/InputEventReceiver.java @@ -21,6 +21,7 @@ import android.os.Build; import android.os.IBinder; import android.os.Looper; import android.os.MessageQueue; +import android.os.Trace; import android.util.Log; import android.util.SparseIntArray; @@ -198,6 +199,15 @@ public abstract class InputEventReceiver { } /** + * Report the 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 + Trace.traceEnd(Trace.TRACE_TAG_INPUT); + } + + /** * Consumes all pending batched input events. * Must be called on the same Looper thread to which the receiver is attached. * diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 390e3ae78143..9fc415d6401f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -16,6 +16,7 @@ package android.view; +import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.InputDevice.SOURCE_CLASS_NONE; @@ -105,6 +106,7 @@ import android.graphics.Color; import android.graphics.FrameInfo; import android.graphics.HardwareRenderer; import android.graphics.HardwareRenderer.FrameDrawingCallback; +import android.graphics.HardwareRendererObserver; import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.PixelFormat; @@ -1191,6 +1193,14 @@ public final class ViewRootImpl implements ViewParent, } mInputEventReceiver = new WindowInputEventReceiver(inputChannel, Looper.myLooper()); + + if (mAttachInfo.mThreadedRenderer != null) { + InputMetricsListener listener = + new InputMetricsListener(mInputEventReceiver); + mHardwareRendererObserver = new HardwareRendererObserver( + listener, listener.data, mHandler, true /*waitForPresentTime*/); + mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver); + } } view.assignParent(this); @@ -8569,6 +8579,34 @@ public final class ViewRootImpl implements ViewParent, } 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]; + if (inputEventId == INVALID_INPUT_EVENT_ID) { + return; + } + final long presentTime = data[FrameMetrics.Index.DISPLAY_PRESENT_TIME]; + if (presentTime <= 0) { + // Present time is not available for this frame. If the present time is not + // available, we cannot compute end-to-end input latency metrics. + return; + } + final long gpuCompletedTime = data[FrameMetrics.Index.GPU_COMPLETED]; + mReceiver.reportLatencyInfo(inputEventId, gpuCompletedTime, presentTime); + } + } + HardwareRendererObserver mHardwareRendererObserver; + final class ConsumeBatchedInputRunnable implements Runnable { @Override public void run() { diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java index 8d1271d7311c..f63749be6df2 100644 --- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java +++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java @@ -23,9 +23,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Binder; import android.os.Build; import android.os.Bundle; -import android.os.Handler; import android.os.IBinder; -import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; @@ -115,8 +113,6 @@ public final class AccessibilityInteractionClient private final Object mInstanceLock = new Object(); - private Handler mMainHandler; - private volatile int mInteractionId = -1; private AccessibilityNodeInfo mFindAccessibilityNodeInfoResult; @@ -127,11 +123,6 @@ public final class AccessibilityInteractionClient private Message mSameThreadMessage; - private int mInteractionIdWaitingForPrefetchResult; - private int mConnectionIdWaitingForPrefetchResult; - private String[] mPackageNamesForNextPrefetchResult; - private Runnable mPrefetchResultRunnable; - /** * @return The client for the current thread. */ @@ -206,10 +197,6 @@ public final class AccessibilityInteractionClient private AccessibilityInteractionClient() { /* reducing constructor visibility */ - Looper mainLooper = Looper.getMainLooper(); - if (mainLooper != null) { - mMainHandler = new Handler(mainLooper); - } } /** @@ -464,16 +451,16 @@ public final class AccessibilityInteractionClient Binder.restoreCallingIdentity(identityToken); } if (packageNames != null) { - AccessibilityNodeInfo info = - getFindAccessibilityNodeInfoResultAndClear(interactionId); - if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_MASK) != 0 - && info != null) { - setInteractionWaitingForPrefetchResult(interactionId, connectionId, - packageNames); - } - finalizeAndCacheAccessibilityNodeInfo(info, connectionId, + List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( + interactionId); + finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, bypassCache, packageNames); - return info; + if (infos != null && !infos.isEmpty()) { + for (int i = 1; i < infos.size(); i++) { + infos.get(i).recycle(); + } + return infos.get(0); + } } } else { if (DEBUG) { @@ -487,15 +474,6 @@ public final class AccessibilityInteractionClient return null; } - private void setInteractionWaitingForPrefetchResult(int interactionId, int connectionId, - String[] packageNames) { - synchronized (mInstanceLock) { - mInteractionIdWaitingForPrefetchResult = interactionId; - mConnectionIdWaitingForPrefetchResult = connectionId; - mPackageNamesForNextPrefetchResult = packageNames; - } - } - private static String idToString(int accessibilityWindowId, long accessibilityNodeId) { return accessibilityWindowId + "/" + AccessibilityNodeInfo.idToString(accessibilityNodeId); @@ -851,59 +829,6 @@ public final class AccessibilityInteractionClient } /** - * {@inheritDoc} - */ - @Override - public void setPrefetchAccessibilityNodeInfoResult(@NonNull List<AccessibilityNodeInfo> infos, - int interactionId) { - List<AccessibilityNodeInfo> infosCopy = null; - int mConnectionIdWaitingForPrefetchResultCopy = -1; - String[] mPackageNamesForNextPrefetchResultCopy = null; - - synchronized (mInstanceLock) { - if (!infos.isEmpty() && mInteractionIdWaitingForPrefetchResult == interactionId) { - if (mMainHandler != null) { - if (mPrefetchResultRunnable != null) { - mMainHandler.removeCallbacks(mPrefetchResultRunnable); - mPrefetchResultRunnable = null; - } - /** - * TODO(b/180957109): AccessibilityCache is prone to deadlocks - * We post caching the prefetched nodes in the main thread. Using the binder - * thread results in "Long monitor contention with owner main" logs where - * service response times may exceed 5 seconds. This is due to the cache calling - * out to the system when refreshing nodes with the lock held. - */ - mPrefetchResultRunnable = () -> finalizeAndCacheAccessibilityNodeInfos( - infos, mConnectionIdWaitingForPrefetchResult, false, - mPackageNamesForNextPrefetchResult); - mMainHandler.post(mPrefetchResultRunnable); - - } else { - for (AccessibilityNodeInfo info : infos) { - infosCopy.add(new AccessibilityNodeInfo(info)); - } - mConnectionIdWaitingForPrefetchResultCopy = - mConnectionIdWaitingForPrefetchResult; - mPackageNamesForNextPrefetchResultCopy = - new String[mPackageNamesForNextPrefetchResult.length]; - for (int i = 0; i < mPackageNamesForNextPrefetchResult.length; i++) { - mPackageNamesForNextPrefetchResultCopy[i] = - mPackageNamesForNextPrefetchResult[i]; - } - } - } - - } - - if (infosCopy != null) { - finalizeAndCacheAccessibilityNodeInfos( - infosCopy, mConnectionIdWaitingForPrefetchResultCopy, false, - mPackageNamesForNextPrefetchResultCopy); - } - } - - /** * Gets the result of a request to perform an accessibility action. * * @param interactionId The interaction id to match the result with the request. diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl index 231e75a19a06..049bb31adbb1 100644 --- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl +++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl @@ -47,15 +47,6 @@ oneway interface IAccessibilityInteractionConnectionCallback { int interactionId); /** - * Sets the result of a prefetch request that returns {@link AccessibilityNodeInfo}s. - * - * @param root The {@link AccessibilityNodeInfo} for which the prefetching is based off of. - * @param infos The result {@link AccessibilityNodeInfo}s. - */ - void setPrefetchAccessibilityNodeInfoResult( - in List<AccessibilityNodeInfo> infos, int interactionId); - - /** * Sets the result of a request to perform an accessibility action. * * @param Whether the action was performed. diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java index db0b48e130a3..c897002c88e9 100644 --- a/core/java/com/android/internal/jank/FrameTracker.java +++ b/core/java/com/android/internal/jank/FrameTracker.java @@ -121,7 +121,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener mChoreographer = choreographer; mSurfaceControlWrapper = surfaceControlWrapper; mHandler = handler; - mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler); + mObserver = new HardwareRendererObserver( + this, mMetricsWrapper.getTiming(), handler, false /*waitForPresentTime*/); mTraceThresholdMissedFrames = traceThresholdMissedFrames; mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis; mListener = listener; diff --git a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java index e153eb2f0933..586607e413d9 100644 --- a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java +++ b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java @@ -46,7 +46,8 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator { long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { final long durationMs = calculateDuration(batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); - final double powerMah = getMeasuredOrEstimatedPower(batteryStats.getScreenDozeEnergy(), + final double powerMah = getMeasuredOrEstimatedPower( + batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(), mPowerEstimator, durationMs, query.shouldForceUsePowerProfileModel()); builder.getOrCreateSystemBatteryConsumerBuilder( SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY) @@ -64,7 +65,8 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator { public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { final long durationMs = calculateDuration(batteryStats, rawRealtimeUs, statsType); - final double powerMah = getMeasuredOrEstimatedPower(batteryStats.getScreenDozeEnergy(), + final double powerMah = getMeasuredOrEstimatedPower( + batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(), mPowerEstimator, durationMs, false); if (powerMah > 0) { BatterySipper bs = new BatterySipper(BatterySipper.DrainType.AMBIENT_DISPLAY, null, 0); @@ -78,5 +80,4 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator { private long calculateDuration(BatteryStats batteryStats, long rawRealtimeUs, int statsType) { return batteryStats.getScreenDozeTime(rawRealtimeUs, statsType) / 1000; } - } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 73527d4a80d8..9ecb0ad09bc4 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -105,7 +105,7 @@ import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader; import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes; import com.android.internal.power.MeasuredEnergyStats; -import com.android.internal.power.MeasuredEnergyStats.StandardEnergyBucket; +import com.android.internal.power.MeasuredEnergyStats.StandardPowerBucket; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.XmlUtils; @@ -169,7 +169,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - static final int VERSION = 193; + static final int VERSION = 194; // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks @@ -996,9 +996,9 @@ public class BatteryStatsImpl extends BatteryStats { int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; /** - * Accumulated global (generally, device-wide total) energy consumption of various consumers + * Accumulated global (generally, device-wide total) charge consumption of various consumers * while on battery. - * Its '<b>custom</b> energy buckets' correspond to the + * Its '<b>custom</b> power buckets' correspond to the * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}). * @@ -1009,6 +1009,8 @@ public class BatteryStatsImpl extends BatteryStats { protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats; /** Last known screen state. Needed for apportioning display energy. */ int mScreenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN; + /** Cpu Power calculator for attributing measured cpu charge consumption to uids */ + @Nullable CpuPowerCalculator mCpuPowerCalculator = null; /** * These provide time bases that discount the time the device is plugged @@ -6965,35 +6967,35 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public long getScreenOnEnergy() { - return getMeasuredEnergyMicroJoules(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON); + public long getScreenOnMeasuredBatteryConsumptionUC() { + return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON); } @Override - public long getScreenDozeEnergy() { - return getMeasuredEnergyMicroJoules(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE); + public long getScreenDozeMeasuredBatteryConsumptionUC() { + return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE); } /** - * Returns the energy in microjoules that the given standard energy bucket consumed. - * Will return {@link #ENERGY_DATA_UNAVAILABLE} if data is unavailable + * Returns the consumption (in microcoulombs) that the given standard power bucket consumed. + * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable * - * @param bucket standard energy bucket of interest - * @return energy (in microjoules) used for this energy bucket + * @param bucket standard power bucket of interest + * @return charge (in microcoulombs) used for this power bucket */ - private long getMeasuredEnergyMicroJoules(@StandardEnergyBucket int bucket) { + private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) { if (mGlobalMeasuredEnergyStats == null) { - return ENERGY_DATA_UNAVAILABLE; + return POWER_DATA_UNAVAILABLE; } - return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketEnergy(bucket); + return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket); } @Override - public @Nullable long[] getCustomMeasuredEnergiesMicroJoules() { + public @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC() { if (mGlobalMeasuredEnergyStats == null) { return null; } - return mGlobalMeasuredEnergyStats.getAccumulatedCustomBucketEnergies(); + return mGlobalMeasuredEnergyStats.getAccumulatedCustomBucketCharges(); } @Override public long getStartClockTime() { @@ -7347,8 +7349,8 @@ public class BatteryStatsImpl extends BatteryStats { private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>(); /** - * Measured energies attributed to this uid while on battery. - * Its '<b>custom</b> energy buckets' correspond to the + * Measured charge consumption by this uid while on battery. + * Its '<b>custom</b> power buckets' correspond to the * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}). * @@ -7768,44 +7770,44 @@ public class BatteryStatsImpl extends BatteryStats { return mUidMeasuredEnergyStats; } - /** Adds the given energy to the given standard energy bucket for this uid. */ - private void addEnergyToStandardBucketLocked(long energyDeltaUJ, - @StandardEnergyBucket int energyBucket) { - getOrCreateMeasuredEnergyStatsLocked() - .updateStandardBucket(energyBucket, energyDeltaUJ); + /** Adds the given charge to the given standard power bucket for this uid. */ + private void addChargeToStandardBucketLocked(long chargeDeltaUC, + @StandardPowerBucket int powerBucket) { + getOrCreateMeasuredEnergyStatsLocked().updateStandardBucket(powerBucket, chargeDeltaUC); } - /** Adds the given energy to the given custom energy bucket for this uid. */ - private void addEnergyToCustomBucketLocked(long energyDeltaUJ, int energyBucket) { - getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(energyBucket, energyDeltaUJ); + /** Adds the given charge to the given custom power bucket for this uid. */ + private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) { + getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC); } /** - * Returns the energy used by this uid for a standard energy bucket of interest. - * @param bucket standard energy bucket of interest - * @return energy (in microjoules) used by this uid for this energy bucket + * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket + * of interest. + * @param bucket standard power bucket of interest + * @return consumption (in microcolombs) used by this uid for this power bucket */ - public long getMeasuredEnergyMicroJoules(@StandardEnergyBucket int bucket) { + public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket) { if (mBsi.mGlobalMeasuredEnergyStats == null || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) { - return ENERGY_DATA_UNAVAILABLE; + return POWER_DATA_UNAVAILABLE; } if (mUidMeasuredEnergyStats == null) { return 0L; // It is supported, but was never filled, so it must be 0 } - return mUidMeasuredEnergyStats.getAccumulatedStandardBucketEnergy(bucket); + return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket); } @Override - public long[] getCustomMeasuredEnergiesMicroJoules() { + public long[] getCustomConsumerMeasuredBatteryConsumptionUC() { if (mBsi.mGlobalMeasuredEnergyStats == null) { return null; } if (mUidMeasuredEnergyStats == null) { // Custom buckets may exist. But all values for this uid are 0 so we report all 0s. - return new long[mBsi.mGlobalMeasuredEnergyStats.getNumberCustomEnergyBuckets()]; + return new long[mBsi.mGlobalMeasuredEnergyStats.getNumberCustomPowerBuckets()]; } - return mUidMeasuredEnergyStats.getAccumulatedCustomBucketEnergies(); + return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges(); } /** @@ -8476,8 +8478,8 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public long getScreenOnEnergy() { - return getMeasuredEnergyMicroJoules(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON); + public long getScreenOnMeasuredBatteryConsumptionUC() { + return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON); } void initNetworkActivityLocked() { @@ -12170,27 +12172,108 @@ public class BatteryStatsImpl extends BatteryStats { } /** - * Accumulate Display energy and distribute it to the correct state and the apps. + * Accumulate Cpu charge consumption and distribute it to the correct state and the apps. + * Only call if device is on battery. + * + * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster + * @param accumulator collection of calculated uid cpu power consumption to smear + * clusterChargeUC against. + */ + @GuardedBy("this") + private void updateCpuMeasuredEnergyStatsLocked(@NonNull long[] clusterChargeUC, + @NonNull CpuDeltaPowerAccumulator accumulator) { + if (DEBUG_ENERGY) { + Slog.d(TAG, + "Updating cpu cluster stats: " + clusterChargeUC.toString()); + } + if (mGlobalMeasuredEnergyStats == null) { + return; + } + + final int numClusters = clusterChargeUC.length; + long totalCpuChargeUC = 0; + for (int i = 0; i < numClusters; i++) { + totalCpuChargeUC += clusterChargeUC[i]; + } + if (totalCpuChargeUC <= 0) return; + + mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_CPU, + totalCpuChargeUC); + + // Calculate the measured microcoulombs/calculated milliamp-hour charge ratio for each + // cluster to normalize each uid's estimated power usage against actual power usage for + // a given cluster. + final double[] clusterChargeRatio = new double[numClusters]; + for (int cluster = 0; cluster < numClusters; cluster++) { + + final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster]; + if (totalClusterChargeMah <= 0.0) { + // This cluster did not have any work on it, since last update. + // Avoid dividing by zero. + clusterChargeRatio[cluster] = 0.0; + } else { + clusterChargeRatio[cluster] = + clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster]; + } + } + + // Assign and distribute power usage to apps based on their calculated cpu cluster charge. + final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size(); + for (int i = 0; i < uidChargeArraySize; i++) { + final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i); + final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i); + + // Iterate each cpu cluster and sum the proportional measured cpu cluster charge to + // get the total cpu charge consumed by a uid. + long uidCpuChargeUC = 0; + for (int cluster = 0; cluster < numClusters; cluster++) { + final double uidClusterChargeMah = uidClusterChargesMah[cluster]; + + // Proportionally allocate the measured cpu cluster charge to a uid using the + // measured charge/calculated charge ratio. Add 0.5 to round the proportional + // charge double to the nearest long value. + final long uidClusterChargeUC = + (long) (uidClusterChargeMah * clusterChargeRatio[cluster] + + 0.5); + + uidCpuChargeUC += uidClusterChargeUC; + } + + if (uidCpuChargeUC < 0) { + Slog.wtf(TAG, + "Unexpected proportional measured charge (" + uidCpuChargeUC + ") for uid " + + uid.mUid); + continue; + } + + uid.addChargeToStandardBucketLocked(uidCpuChargeUC, + MeasuredEnergyStats.POWER_BUCKET_CPU); + } + } + + /** + * Accumulate Display charge consumption and distribute it to the correct state and the apps. * * NOTE: The algorithm used makes the strong assumption that app foreground activity time * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported). * To the extent that those assumptions are violated, the algorithm will err. * - * @param energyUJ amount of energy (microjoules) used by Display since this was last called. + * @param chargeUC amount of charge (microcoulombs) used by Display since this was last called. * @param screenState screen state at the time this data collection was scheduled */ @GuardedBy("this") - public void updateDisplayEnergyLocked(long energyUJ, int screenState, long elapsedRealtimeMs) { - if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + energyUJ); + public void updateDisplayMeasuredEnergyStatsLocked(long chargeUC, int screenState, + long elapsedRealtimeMs) { + if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + chargeUC); if (mGlobalMeasuredEnergyStats == null) { return; } - final @StandardEnergyBucket int energyBucket = - MeasuredEnergyStats.getDisplayEnergyBucket(mScreenStateAtLastEnergyMeasurement); + final @StandardPowerBucket int powerBucket = + MeasuredEnergyStats.getDisplayPowerBucket(mScreenStateAtLastEnergyMeasurement); mScreenStateAtLastEnergyMeasurement = screenState; - if (!mOnBatteryInternal || energyUJ <= 0) { + if (!mOnBatteryInternal || chargeUC <= 0) { // There's nothing further to update. return; } @@ -12205,13 +12288,13 @@ public class BatteryStatsImpl extends BatteryStats { return; } - mGlobalMeasuredEnergyStats.updateStandardBucket(energyBucket, energyUJ); + mGlobalMeasuredEnergyStats.updateStandardBucket(powerBucket, chargeUC); // Now we blame individual apps, but only if the display was ON. - if (energyBucket != MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON) { + if (powerBucket != MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON) { return; } - // TODO(b/175726779): Consider unifying the code with the non-rail display energy blaming. + // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming. // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is // 'double counted' and will simply exceed the realtime that elapsed. @@ -12230,7 +12313,7 @@ public class BatteryStatsImpl extends BatteryStats { fgTimeMsArray.put(uid, fgTimeMs); totalFgTimeMs += fgTimeMs; } - long totalDisplayEnergyMJ = energyUJ / 1000; // not final + long totalDisplayChargeMC = chargeUC / 1000; // not final // Actually assign and distribute power usage to apps based on their fg time since mark. // TODO(b/175726326): Decide on 'energy' units and make sure algorithm won't overflow. @@ -12240,47 +12323,47 @@ public class BatteryStatsImpl extends BatteryStats { final long fgTimeMs = fgTimeMsArray.valueAt(i); // Using long division: "appEnergy = totalEnergy * appFg/totalFg + 0.5" with rounding - final long appDisplayEnergyMJ = - (totalDisplayEnergyMJ * fgTimeMs + (totalFgTimeMs / 2)) + final long appDisplayChargeMC = + (totalDisplayChargeMC * fgTimeMs + (totalFgTimeMs / 2)) / totalFgTimeMs; - uid.addEnergyToStandardBucketLocked(appDisplayEnergyMJ * 1000, energyBucket); + uid.addChargeToStandardBucketLocked(appDisplayChargeMC * 1000, powerBucket); // To mitigate round-off errors, remove this app from numerator & denominator totals - totalDisplayEnergyMJ -= appDisplayEnergyMJ; + totalDisplayChargeMC -= appDisplayChargeMC; totalFgTimeMs -= fgTimeMs; } } /** - * Accumulate Custom energy bucket energy, globally and for each app. + * Accumulate Custom power bucket charge, globally and for each app. * - * @param totalEnergyUJ energy (microjoules) used for this bucket since this was last called. - * @param uidEnergies map of uid->energy (microjoules) for this bucket since last called. - * Data inside uidEnergies will not be modified (treated immutable). + * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called. + * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called. + * Data inside uidCharges will not be modified (treated immutable). * Uids not already known to BatteryStats will be ignored. */ - public void updateCustomMeasuredEnergyDataLocked(int customEnergyBucket, - long totalEnergyUJ, @Nullable SparseLongArray uidEnergies) { + public void updateCustomMeasuredEnergyStatsLocked(int customPowerBucket, + long totalChargeUC, @Nullable SparseLongArray uidCharges) { if (DEBUG_ENERGY) { - Slog.d(TAG, "Updating attributed measured energy stats for custom bucket " - + customEnergyBucket - + " with total energy " + totalEnergyUJ - + " and uid energies " + String.valueOf(uidEnergies)); + Slog.d(TAG, "Updating attributed measured charge stats for custom bucket " + + customPowerBucket + + " with total charge " + totalChargeUC + + " and uid charges " + String.valueOf(uidCharges)); } if (mGlobalMeasuredEnergyStats == null) return; - if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalEnergyUJ <= 0) return; + if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return; - mGlobalMeasuredEnergyStats.updateCustomBucket(customEnergyBucket, totalEnergyUJ); + mGlobalMeasuredEnergyStats.updateCustomBucket(customPowerBucket, totalChargeUC); - if (uidEnergies == null) return; - final int numUids = uidEnergies.size(); + if (uidCharges == null) return; + final int numUids = uidCharges.size(); for (int i = 0; i < numUids; i++) { - final int uidInt = mapUid(uidEnergies.keyAt(i)); - final long uidEnergyUJ = uidEnergies.valueAt(i); - if (uidEnergyUJ == 0) continue; + final int uidInt = mapUid(uidCharges.keyAt(i)); + final long uidChargeUC = uidCharges.valueAt(i); + if (uidChargeUC == 0) continue; final Uid uidObj = getAvailableUidStatsLocked(uidInt); if (uidObj != null) { - uidObj.addEnergyToCustomBucketLocked(uidEnergyUJ, customEnergyBucket); + uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket); } else { // Ignore any uid not already known to BatteryStats, rather than creating a new Uid. // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated @@ -12288,8 +12371,8 @@ public class BatteryStatsImpl extends BatteryStats { // Recently removed uids (especially common for isolated uids) can reach this path // and are ignored. if (!Process.isIsolated(uidInt)) { - Slog.w(TAG, "Received measured energy " + totalEnergyUJ + " for custom bucket " - + customEnergyBucket + " for non-existent uid " + uidInt); + Slog.w(TAG, "Received measured charge " + totalChargeUC + " for custom bucket " + + customPowerBucket + " for non-existent uid " + uidInt); } } } @@ -12416,6 +12499,64 @@ public class BatteryStatsImpl extends BatteryStats { } /** + * Object for calculating and accumulating the estimated cpu power used while reading the + * various cpu kernel files. + */ + @VisibleForTesting + public static class CpuDeltaPowerAccumulator { + // Keeps track of total charge used per cluster. + public final double[] totalClusterChargesMah; + // Keeps track of charge used per cluster per uid. + public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah; + + private final CpuPowerCalculator mCalculator; + private Uid mCachedUid = null; + private double[] mUidClusterCache = null; + + CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) { + mCalculator = calculator; + totalClusterChargesMah = new double[nClusters]; + perUidCpuClusterChargesMah = new ArrayMap<>(); + } + + /** Add per cpu cluster durations to the currently cached uid. */ + public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) { + final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid); + for (int cluster = 0; cluster < durationsMs.length; cluster++) { + final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster, + durationsMs[cluster]); + uidChargesMah[cluster] += estimatedDeltaMah; + totalClusterChargesMah[cluster] += estimatedDeltaMah; + } + } + + /** Add per speed per cpu cluster durations to the currently cached uid. */ + public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed, + long durationsMs) { + final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid); + final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed, + durationsMs); + uidChargesMah[cluster] += estimatedDeltaMah; + totalClusterChargesMah[cluster] += estimatedDeltaMah; + } + + private double[] getOrCreateUidCpuClusterCharges(Uid uid) { + // Repeated additions on the same uid is very likely. + // Skip a lookup if getting the same uid as the last get. + if (uid == mCachedUid) return mUidClusterCache; + + double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid); + if (uidChargesMah == null) { + uidChargesMah = new double[totalClusterChargesMah.length]; + perUidCpuClusterChargesMah.put(uid, uidChargesMah); + } + mCachedUid = uid; + mUidClusterCache = uidChargesMah; + return uidChargesMah; + } + } + + /** * Read and distribute CPU usage across apps. If their are partial wakelocks being held * and we are on battery with screen off, we give more of the cpu time to those apps holding * wakelocks. If the screen is on, we just assign the actual cpu time an app used. @@ -12424,7 +12565,8 @@ public class BatteryStatsImpl extends BatteryStats { * buckets. */ @GuardedBy("this") - public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) { + public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff, + long[] measuredCpuClusterChargeUC) { if (mPowerProfile == null) { return; } @@ -12478,21 +12620,48 @@ public class BatteryStatsImpl extends BatteryStats { mUserInfoProvider.refreshUserIds(); final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable() ? null : new SparseLongArray(); + + final CpuDeltaPowerAccumulator powerAccumulator; + if (mGlobalMeasuredEnergyStats != null + && mGlobalMeasuredEnergyStats.isStandardBucketSupported( + MeasuredEnergyStats.POWER_BUCKET_CPU) && mCpuPowerCalculator != null) { + if (measuredCpuClusterChargeUC == null) { + Slog.wtf(TAG, + "POWER_BUCKET_CPU supported but no measured Cpu Cluster charge reported " + + "on updateCpuTimeLocked!"); + powerAccumulator = null; + } else { + // Cpu Measured Energy is supported, create an object to accumulate the estimated + // charge consumption since the last cpu update + final int numClusters = mPowerProfile.getNumCpuClusters(); + powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator, numClusters); + } + } else { + powerAccumulator = null; + } + readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery); // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu // freqs, so no need to approximate these values. if (updatedUids != null) { - updateClusterSpeedTimes(updatedUids, onBattery); + updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator); } - readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff); + readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff, + powerAccumulator); mNumAllUidCpuTimeReads += 2; if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) { + // Cpu Active times do not get any info ony how to attribute measured Cpu Cluster + // charge, so not need to provide the powerAccumulator readKernelUidCpuActiveTimesLocked(onBattery); - readKernelUidCpuClusterTimesLocked(onBattery); + readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator); mNumAllUidCpuTimeReads += 2; } updateSystemServerThreadStats(); + + if (powerAccumulator != null) { + updateCpuMeasuredEnergyStatsLocked(measuredCpuClusterChargeUC, powerAccumulator); + } } /** @@ -12579,12 +12748,16 @@ public class BatteryStatsImpl extends BatteryStats { /** * Take snapshot of cpu times (aggregated over all uids) at different frequencies and - * calculate cpu times spent by each uid at different frequencies. + * calculate cpu times spent by each uid at different frequencies. Will also add estimated + * power consumptions, if powerAccumulator data structure is provided. * - * @param updatedUids The uids for which times spent at different frequencies are calculated. + * @param updatedUids The uids for which times spent at different frequencies are calculated. + * @param onBattery whether or not this is onBattery + * @param powerAccumulator object to accumulate the estimated cluster charge consumption. */ @VisibleForTesting - public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) { + public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery, + @Nullable CpuDeltaPowerAccumulator powerAccumulator) { long totalCpuClustersTimeMs = 0; // Read the time spent for each cluster at various cpu frequencies. final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][]; @@ -12626,9 +12799,15 @@ public class BatteryStatsImpl extends BatteryStats { if (cpuSpeeds[speed] == null) { cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase); } - cpuSpeeds[speed].addCountLocked(appCpuTimeUs + final long deltaSpeedCount = appCpuTimeUs * clusterSpeedTimesMs[cluster][speed] - / totalCpuClustersTimeMs, onBattery); + / totalCpuClustersTimeMs; + cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery); + + if (powerAccumulator != null) { + powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster, + speed, deltaSpeedCount); + } } } } @@ -12750,13 +12929,18 @@ public class BatteryStatsImpl extends BatteryStats { /** * Take a snapshot of the cpu times spent by each uid in each freq and update the - * corresponding counters. + * corresponding counters. Will also add estimated power consumptions, if powerAccumulator + * data structure is provided. * * @param partialTimers The wakelock holders among which the cpu freq times will be distributed. + * @param onBattery whether or not this is onBattery + * @param onBatteryScreenOff whether or not this is onBattery with the screen off. + * @param powerAccumulator object to accumulate the estimated cluster charge consumption. */ @VisibleForTesting public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers, - boolean onBattery, boolean onBatteryScreenOff) { + boolean onBattery, boolean onBatteryScreenOff, + @Nullable CpuDeltaPowerAccumulator powerAccumulator) { final boolean perClusterTimesAvailable = mCpuUidFreqTimeReader.perClusterTimesAvailable(); final int numWakelocks = partialTimers == null ? 0 : partialTimers.size(); @@ -12765,7 +12949,9 @@ public class BatteryStatsImpl extends BatteryStats { final long startTimeMs = mClocks.uptimeMillis(); final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final List<Integer> uidsToRemove = new ArrayList<>(); - mCpuUidFreqTimeReader.readDelta(false, (uid, cpuFreqTimeMs) -> { + // If power is being accumulated for attribution, data needs to be read immediately. + final boolean forceRead = powerAccumulator != null; + mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { uidsToRemove.add(uid); @@ -12828,6 +13014,11 @@ public class BatteryStatsImpl extends BatteryStats { appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000; } cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery); + + if (powerAccumulator != null) { + powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster, + speed, appAllocationUs / 1000); + } freqIndex++; } } @@ -12868,6 +13059,11 @@ public class BatteryStatsImpl extends BatteryStats { mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i); cpuTimeUs[speed].addCountLocked(allocationUs, onBattery); mWakeLockAllocationsUs[cluster][speed] -= allocationUs; + + if (powerAccumulator != null) { + powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster, + speed, allocationUs / 1000); + } } } } @@ -12910,14 +13106,21 @@ public class BatteryStatsImpl extends BatteryStats { /** * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding - * counters. + * counters. Will also add estimated power consumptions, if powerAccumulator data structure + * is provided. + * + * @param onBattery whether or not this is onBattery + * @param powerAccumulator object to accumulate the estimated cluster charge consumption. */ @VisibleForTesting - public void readKernelUidCpuClusterTimesLocked(boolean onBattery) { + public void readKernelUidCpuClusterTimesLocked(boolean onBattery, + @Nullable CpuDeltaPowerAccumulator powerAccumulator) { final long startTimeMs = mClocks.uptimeMillis(); final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final List<Integer> uidsToRemove = new ArrayList<>(); - mCpuUidClusterTimeReader.readDelta(false, (uid, cpuClusterTimesMs) -> { + // If power is being accumulated for attribution, data needs to be read immediately. + final boolean forceRead = powerAccumulator != null; + mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { uidsToRemove.add(uid); @@ -12931,6 +13134,10 @@ public class BatteryStatsImpl extends BatteryStats { } final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs); u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery); + + if (powerAccumulator != null) { + powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs); + } }); for (int uid : uidsToRemove) { mCpuUidClusterTimeReader.removeUid(uid); @@ -13197,8 +13404,9 @@ public class BatteryStatsImpl extends BatteryStats { } } + mBatteryVoltageMv = voltageMv; + if (ENABLE_FOREGROUND_STATS_COLLECTION) { - mBatteryVoltageMv = voltageMv; if (onBattery) { final long energyNwh = (voltageMv * (long) chargeUah); final long energyDelta = mLastBatteryEnergyCapacityNwh - energyNwh; @@ -13982,9 +14190,9 @@ public class BatteryStatsImpl extends BatteryStats { registerUsbStateReceiver(context); } /** - * Initialize the measured energy stats data structures. + * Initialize the measured charge stats data structures. * - * @param supportedStandardBuckets boolean array indicating which {@link StandardEnergyBucket}s + * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s * are currently supported. * If null, none are supported (regardless of numCustomBuckets). * @param numCustomBuckets number of custom (OTHER) EnergyConsumers on this device @@ -13997,27 +14205,39 @@ public class BatteryStatsImpl extends BatteryStats { if (supportedStandardBuckets == null) { if (mGlobalMeasuredEnergyStats != null) { - // Measured energy buckets no longer supported, wipe out the existing data. + // Measured energy no longer supported, wipe out the existing data. supportedBucketMismatch = true; } - } else if (mGlobalMeasuredEnergyStats == null) { - mGlobalMeasuredEnergyStats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - return; } else { - supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo( - supportedStandardBuckets, numCustomBuckets); + if (mGlobalMeasuredEnergyStats == null) { + mGlobalMeasuredEnergyStats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + return; + } else { + supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo( + supportedStandardBuckets, numCustomBuckets); + } + + if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU]) { + mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile); + } } if (supportedBucketMismatch) { - mGlobalMeasuredEnergyStats = supportedStandardBuckets == null ? - null : new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - // Supported energy buckets changed since last boot. + mGlobalMeasuredEnergyStats = supportedStandardBuckets == null + ? null : new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + // Supported power buckets changed since last boot. // Existing data is no longer reliable. resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime()); } } + /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */ + @GuardedBy("this") + public int getBatteryVoltageMvLocked() { + return mBatteryVoltageMv; + } + @VisibleForTesting public final class Constants extends ContentObserver { public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE @@ -14293,11 +14513,11 @@ public class BatteryStatsImpl extends BatteryStats { } /** - * Dump measured energy stats + * Dump measured charge stats */ @GuardedBy("this") public void dumpMeasuredEnergyStatsLocked(PrintWriter pw) { - pw.printf("On battery measured energy stats (microjoules) \n"); + pw.printf("On battery measured charge stats (microcoulombs) \n"); if (mGlobalMeasuredEnergyStats == null) { pw.printf(" Not supported on this device.\n"); return; @@ -14314,7 +14534,7 @@ public class BatteryStatsImpl extends BatteryStats { } } - /** Dump measured energy stats for the given uid */ + /** Dump measured charge stats for the given uid */ @GuardedBy("this") private void dumpMeasuredEnergyStatsLocked(PrintWriter pw, String name, MeasuredEnergyStats stats) { diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index 619cd8e2fc27..6dd612e4c9bf 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -123,10 +123,10 @@ public class BatteryUsageStatsProvider { final long realtimeUs = mStats.mClocks.elapsedRealtime() * 1000; final long uptimeUs = mStats.mClocks.uptimeMillis() * 1000; - final long[] customMeasuredEnergiesMicroJoules = - mStats.getCustomMeasuredEnergiesMicroJoules(); - final int customPowerComponentCount = customMeasuredEnergiesMicroJoules != null - ? customMeasuredEnergiesMicroJoules.length + final long[] customMeasuredChargesUC = + mStats.getCustomConsumerMeasuredBatteryConsumptionUC(); + final int customPowerComponentCount = customMeasuredChargesUC != null + ? customMeasuredChargesUC.length : 0; // TODO(b/174186358): read extra time component number from configuration diff --git a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java index 2606d80eaa09..9941e30f5d1c 100644 --- a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java +++ b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java @@ -35,7 +35,7 @@ public class CustomMeasuredPowerCalculator extends PowerCalculator { long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { super.calculate(builder, batteryStats, rawRealtimeUs, rawUptimeUs, query); final double[] customMeasuredPowerMah = calculateMeasuredEnergiesMah( - batteryStats.getCustomMeasuredEnergiesMicroJoules()); + batteryStats.getCustomConsumerMeasuredBatteryConsumptionUC()); if (customMeasuredPowerMah != null) { final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder = builder.getOrCreateSystemBatteryConsumerBuilder( @@ -52,7 +52,7 @@ public class CustomMeasuredPowerCalculator extends PowerCalculator { protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { final double[] customMeasuredPowerMah = calculateMeasuredEnergiesMah( - u.getCustomMeasuredEnergiesMicroJoules()); + u.getCustomConsumerMeasuredBatteryConsumptionUC()); if (customMeasuredPowerMah != null) { for (int i = 0; i < customMeasuredPowerMah.length; i++) { app.setConsumedPowerForCustomComponent( @@ -65,20 +65,20 @@ public class CustomMeasuredPowerCalculator extends PowerCalculator { @Override protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType) { - updateCustomMeasuredPowerMah(app, u.getCustomMeasuredEnergiesMicroJoules()); + updateCustomMeasuredPowerMah(app, u.getCustomConsumerMeasuredBatteryConsumptionUC()); } - private void updateCustomMeasuredPowerMah(BatterySipper sipper, long[] measuredEnergiesUJ) { - sipper.customMeasuredPowerMah = calculateMeasuredEnergiesMah(measuredEnergiesUJ); + private void updateCustomMeasuredPowerMah(BatterySipper sipper, long[] measuredChargeUC) { + sipper.customMeasuredPowerMah = calculateMeasuredEnergiesMah(measuredChargeUC); } - private double[] calculateMeasuredEnergiesMah(long[] measuredEnergiesUJ) { - if (measuredEnergiesUJ == null) { + private double[] calculateMeasuredEnergiesMah(long[] measuredChargeUC) { + if (measuredChargeUC == null) { return null; } - final double[] measuredEnergiesMah = new double[measuredEnergiesUJ.length]; - for (int i = 0; i < measuredEnergiesUJ.length; i++) { - measuredEnergiesMah[i] = uJtoMah(measuredEnergiesUJ[i]); + final double[] measuredEnergiesMah = new double[measuredChargeUC.length]; + for (int i = 0; i < measuredChargeUC.length; i++) { + measuredEnergiesMah[i] = uCtoMah(measuredChargeUC[i]); } return measuredEnergiesMah; } diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java index fe4fb7afa1f5..72385e273cf0 100644 --- a/core/java/com/android/internal/os/PowerCalculator.java +++ b/core/java/com/android/internal/os/PowerCalculator.java @@ -30,6 +30,8 @@ import java.util.Locale; */ public abstract class PowerCalculator { + protected static final double MILLIAMPHOUR_PER_MICROCOULOMB = 1.0 / 1000.0 / 60.0 / 60.0; + /** * Attributes the total amount of power used by this subsystem to various consumers such * as apps. @@ -115,12 +117,12 @@ public abstract class PowerCalculator { /** * Returns either the measured energy converted to mAh or a usage-based estimate. */ - protected static double getMeasuredOrEstimatedPower(long measuredEnergyUj, + protected static double getMeasuredOrEstimatedPower(long measuredEnergyUC, UsageBasedPowerEstimator powerEstimator, long durationMs, boolean forceUsePowerProfileModel) { - if (measuredEnergyUj != BatteryStats.ENERGY_DATA_UNAVAILABLE + if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE && !forceUsePowerProfileModel) { - return uJtoMah(measuredEnergyUj); + return uCtoMah(measuredEnergyUC); } return powerEstimator.calculatePower(durationMs); } @@ -156,13 +158,7 @@ public abstract class PowerCalculator { return String.format(Locale.ENGLISH, format, power); } - static double uJtoMah(long energyUJ) { - if (energyUJ == 0) { - return 0; - } - - // TODO(b/173765509): Convert properly. This is mJ / V * (h/3600s) = mAh with V = 3.7 fixed. - // Leaving for later since desired units of energy have yet to be decided - return energyUJ / 1000.0 / 3.7 / 3600; + static double uCtoMah(long chargeUC) { + return chargeUC * MILLIAMPHOUR_PER_MICROCOULOMB; } } diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java index 5dca8d5e70fa..d94bb31f58bf 100644 --- a/core/java/com/android/internal/os/ScreenPowerCalculator.java +++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java @@ -141,9 +141,9 @@ public class ScreenPowerCalculator extends PowerCalculator { statsType); if (!forceUsePowerProfileModel) { - final long energyUJ = batteryStats.getScreenOnEnergy(); - if (energyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) { - totalPowerAndDuration.powerMah = uJtoMah(energyUJ); + final long chargeUC = batteryStats.getScreenOnMeasuredBatteryConsumptionUC(); + if (chargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) { + totalPowerAndDuration.powerMah = uCtoMah(chargeUC); return true; } } @@ -157,14 +157,14 @@ public class ScreenPowerCalculator extends PowerCalculator { BatteryStats.Uid u, long rawRealtimeUs) { appPowerAndDuration.durationMs = getProcessForegroundTimeMs(u, rawRealtimeUs); - final long energyUJ = u.getScreenOnEnergy(); - if (energyUJ < 0) { + final long chargeUC = u.getScreenOnMeasuredBatteryConsumptionUC(); + if (chargeUC < 0) { Slog.wtf(TAG, "Screen energy not supported, so calculateApp shouldn't de called"); appPowerAndDuration.powerMah = 0; return; } - appPowerAndDuration.powerMah = uJtoMah(energyUJ); + appPowerAndDuration.powerMah = uCtoMah(chargeUC); } private long calculateDuration(BatteryStats batteryStats, long rawRealtimeUs, int statsType) { diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java index d49203c731e9..e3d5464ca413 100644 --- a/core/java/com/android/internal/power/MeasuredEnergyStats.java +++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java @@ -17,7 +17,7 @@ package com.android.internal.power; -import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE; +import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; import android.annotation.IntDef; import android.annotation.NonNull; @@ -34,8 +34,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * Tracks the measured energy usage of various subsystems according to their - * {@link StandardEnergyBucket} or custom energy bucket (which is tied to + * Tracks the measured charge consumption of various subsystems according to their + * {@link StandardPowerBucket} or custom power bucket (which is tied to * {@link android.hardware.power.stats.EnergyConsumer.ordinal}). * * This class doesn't use a TimeBase, and instead requires manually decisions about when to @@ -46,51 +46,53 @@ public class MeasuredEnergyStats { private static final String TAG = "MeasuredEnergyStats"; // Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} MUST be updated if standard - // energy bucket integers are modified/added/removed. - public static final int ENERGY_BUCKET_UNKNOWN = -1; - public static final int ENERGY_BUCKET_SCREEN_ON = 0; - public static final int ENERGY_BUCKET_SCREEN_DOZE = 1; - public static final int ENERGY_BUCKET_SCREEN_OTHER = 2; - public static final int NUMBER_STANDARD_ENERGY_BUCKETS = 3; // Buckets above this are custom. - - @IntDef(prefix = {"ENERGY_BUCKET_"}, value = { - ENERGY_BUCKET_UNKNOWN, - ENERGY_BUCKET_SCREEN_ON, - ENERGY_BUCKET_SCREEN_DOZE, - ENERGY_BUCKET_SCREEN_OTHER, + // power bucket integers are modified/added/removed. + public static final int POWER_BUCKET_UNKNOWN = -1; + public static final int POWER_BUCKET_SCREEN_ON = 0; + public static final int POWER_BUCKET_SCREEN_DOZE = 1; + public static final int POWER_BUCKET_SCREEN_OTHER = 2; + public static final int POWER_BUCKET_CPU = 3; + public static final int NUMBER_STANDARD_POWER_BUCKETS = 4; // Buckets above this are custom. + + @IntDef(prefix = {"POWER_BUCKET_"}, value = { + POWER_BUCKET_UNKNOWN, + POWER_BUCKET_SCREEN_ON, + POWER_BUCKET_SCREEN_DOZE, + POWER_BUCKET_SCREEN_OTHER, + POWER_BUCKET_CPU, }) @Retention(RetentionPolicy.SOURCE) - public @interface StandardEnergyBucket { + public @interface StandardPowerBucket { } /** - * Total energy (in microjoules) that an energy bucket (including both - * {@link StandardEnergyBucket} and custom buckets) has accumulated since the last reset. - * Values MUST be non-zero or ENERGY_DATA_UNAVAILABLE. Accumulation only occurs + * Total charge (in microcoulombs) that a power bucket (including both + * {@link StandardPowerBucket} and custom buckets) has accumulated since the last reset. + * Values MUST be non-zero or POWER_DATA_UNAVAILABLE. Accumulation only occurs * while the necessary conditions are satisfied (e.g. on battery). * - * Energy for both {@link StandardEnergyBucket}s and custom energy buckets are stored in this + * Charge for both {@link StandardPowerBucket}s and custom power buckets are stored in this * array, and may internally both referred to as 'buckets'. This is an implementation detail; * externally, we differentiate between these two data sources. * * Warning: Long array is used for access speed. If the number of supported subsystems * becomes large, consider using an alternate data structure such as a SparseLongArray. */ - private final long[] mAccumulatedEnergiesMicroJoules; + private final long[] mAccumulatedChargeMicroCoulomb; /** - * Creates a MeasuredEnergyStats set to support the provided energy buckets. - * supportedStandardBuckets must be of size {@link #NUMBER_STANDARD_ENERGY_BUCKETS}. - * numCustomBuckets >= 0 is the number of (non-standard) custom energy buckets on the device. + * Creates a MeasuredEnergyStats set to support the provided power buckets. + * supportedStandardBuckets must be of size {@link #NUMBER_STANDARD_POWER_BUCKETS}. + * numCustomBuckets >= 0 is the number of (non-standard) custom power buckets on the device. */ public MeasuredEnergyStats(boolean[] supportedStandardBuckets, int numCustomBuckets) { - final int numTotalBuckets = NUMBER_STANDARD_ENERGY_BUCKETS + numCustomBuckets; - mAccumulatedEnergiesMicroJoules = new long[numTotalBuckets]; - // Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE. + final int numTotalBuckets = NUMBER_STANDARD_POWER_BUCKETS + numCustomBuckets; + mAccumulatedChargeMicroCoulomb = new long[numTotalBuckets]; + // Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE. // All custom buckets are, by definition, supported, so their values stay at 0. - for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_ENERGY_BUCKETS; stdBucket++) { + for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) { if (!supportedStandardBuckets[stdBucket]) { - mAccumulatedEnergiesMicroJoules[stdBucket] = ENERGY_DATA_UNAVAILABLE; + mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE; } } } @@ -101,12 +103,12 @@ public class MeasuredEnergyStats { */ private MeasuredEnergyStats(MeasuredEnergyStats template) { final int numIndices = template.getNumberOfIndices(); - mAccumulatedEnergiesMicroJoules = new long[numIndices]; - // Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE. + mAccumulatedChargeMicroCoulomb = new long[numIndices]; + // Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE. // All custom buckets are, by definition, supported, so their values stay at 0. - for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_ENERGY_BUCKETS; stdBucket++) { + for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) { if (!template.isIndexSupported(stdBucket)) { - mAccumulatedEnergiesMicroJoules[stdBucket] = ENERGY_DATA_UNAVAILABLE; + mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE; } } } @@ -124,20 +126,20 @@ public class MeasuredEnergyStats { * See {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}. */ private MeasuredEnergyStats(int numIndices) { - mAccumulatedEnergiesMicroJoules = new long[numIndices]; + mAccumulatedChargeMicroCoulomb = new long[numIndices]; } /** Construct from parcel. */ public MeasuredEnergyStats(Parcel in) { final int size = in.readInt(); - mAccumulatedEnergiesMicroJoules = new long[size]; - in.readLongArray(mAccumulatedEnergiesMicroJoules); + mAccumulatedChargeMicroCoulomb = new long[size]; + in.readLongArray(mAccumulatedChargeMicroCoulomb); } /** Write to parcel */ public void writeToParcel(Parcel out) { - out.writeInt(mAccumulatedEnergiesMicroJoules.length); - out.writeLongArray(mAccumulatedEnergiesMicroJoules); + out.writeInt(mAccumulatedChargeMicroCoulomb.length); + out.writeLongArray(mAccumulatedChargeMicroCoulomb); } /** @@ -153,11 +155,11 @@ public class MeasuredEnergyStats { final int numWrittenEntries = in.readInt(); for (int entry = 0; entry < numWrittenEntries; entry++) { final int index = in.readInt(); - final long energyUJ = in.readLong(); + final long chargeUC = in.readLong(); if (overwriteAvailability) { - mAccumulatedEnergiesMicroJoules[index] = energyUJ; + mAccumulatedChargeMicroCoulomb[index] = chargeUC; } else { - setValueIfSupported(index, energyUJ); + setValueIfSupported(index, chargeUC); } } } @@ -172,14 +174,14 @@ public class MeasuredEnergyStats { final int posOfNumWrittenEntries = out.dataPosition(); out.writeInt(0); int numWrittenEntries = 0; - // Write only the supported buckets (with non-zero energy, if applicable). - for (int index = 0; index < mAccumulatedEnergiesMicroJoules.length; index++) { - final long energy = mAccumulatedEnergiesMicroJoules[index]; - if (energy < 0) continue; - if (energy == 0 && skipZero) continue; + // Write only the supported buckets (with non-zero charge, if applicable). + for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) { + final long charge = mAccumulatedChargeMicroCoulomb[index]; + if (charge < 0) continue; + if (charge == 0 && skipZero) continue; out.writeInt(index); - out.writeLong(mAccumulatedEnergiesMicroJoules[index]); + out.writeLong(charge); numWrittenEntries++; } final int currPos = out.dataPosition(); @@ -190,80 +192,82 @@ public class MeasuredEnergyStats { /** Get number of possible buckets, including both standard and custom ones. */ private int getNumberOfIndices() { - return mAccumulatedEnergiesMicroJoules.length; + return mAccumulatedChargeMicroCoulomb.length; } - /** Updates the given standard energy bucket with the given energy if accumulate is true. */ - public void updateStandardBucket(@StandardEnergyBucket int bucket, long energyDeltaUJ) { + + /** Updates the given standard power bucket with the given charge if accumulate is true. */ + public void updateStandardBucket(@StandardPowerBucket int bucket, long chargeDeltaUC) { checkValidStandardBucket(bucket); - updateEntry(bucket, energyDeltaUJ); + updateEntry(bucket, chargeDeltaUC); } - /** Updates the given custom energy bucket with the given energy if accumulate is true. */ - public void updateCustomBucket(int customBucket, long energyDeltaUJ) { + /** Updates the given custom power bucket with the given charge if accumulate is true. */ + public void updateCustomBucket(int customBucket, long chargeDeltaUC) { if (!isValidCustomBucket(customBucket)) { Slog.e(TAG, "Attempted to update invalid custom bucket " + customBucket); return; } final int index = customBucketToIndex(customBucket); - updateEntry(index, energyDeltaUJ); + updateEntry(index, chargeDeltaUC); } - /** Updates the given index with the given energy if accumulate is true. */ - private void updateEntry(int index, long energyDeltaUJ) { - if (mAccumulatedEnergiesMicroJoules[index] >= 0L) { - mAccumulatedEnergiesMicroJoules[index] += energyDeltaUJ; + /** Updates the given index with the given charge if accumulate is true. */ + private void updateEntry(int index, long chargeDeltaUC) { + if (mAccumulatedChargeMicroCoulomb[index] >= 0L) { + mAccumulatedChargeMicroCoulomb[index] += chargeDeltaUC; } else { - Slog.wtf(TAG, "Attempting to add " + energyDeltaUJ + " to unavailable bucket " + Slog.wtf(TAG, "Attempting to add " + chargeDeltaUC + " to unavailable bucket " + getBucketName(index) + " whose value was " - + mAccumulatedEnergiesMicroJoules[index]); + + mAccumulatedChargeMicroCoulomb[index]); } } /** - * Return accumulated energy (in microjoules) for a standard energy bucket since last reset. - * Returns {@link android.os.BatteryStats#ENERGY_DATA_UNAVAILABLE} if this data is unavailable. - * @throws IllegalArgumentException if no such {@link StandardEnergyBucket}. + * Return accumulated charge (in microcouloumb) for a standard power bucket since last reset. + * Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable. + * @throws IllegalArgumentException if no such {@link StandardPowerBucket}. */ - public long getAccumulatedStandardBucketEnergy(@StandardEnergyBucket int bucket) { + public long getAccumulatedStandardBucketCharge(@StandardPowerBucket int bucket) { checkValidStandardBucket(bucket); - return mAccumulatedEnergiesMicroJoules[bucket]; + return mAccumulatedChargeMicroCoulomb[bucket]; } /** - * Return accumulated energy (in microjoules) for the a custom energy bucket since last reset. - * Returns {@link android.os.BatteryStats#ENERGY_DATA_UNAVAILABLE} if this data is unavailable. + * Return accumulated charge (in microcoulomb) for the a custom power bucket since last + * reset. + * Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable. */ @VisibleForTesting - public long getAccumulatedCustomBucketEnergy(int customBucket) { + public long getAccumulatedCustomBucketCharge(int customBucket) { if (!isValidCustomBucket(customBucket)) { - return ENERGY_DATA_UNAVAILABLE; + return POWER_DATA_UNAVAILABLE; } - return mAccumulatedEnergiesMicroJoules[customBucketToIndex(customBucket)]; + return mAccumulatedChargeMicroCoulomb[customBucketToIndex(customBucket)]; } /** - * Return accumulated energies (in microjoules) for all custom energy buckets since last reset. + * Return accumulated charge (in microcoulomb) for all custom power buckets since last reset. */ - public @NonNull long[] getAccumulatedCustomBucketEnergies() { - final long[] energies = new long[getNumberCustomEnergyBuckets()]; - for (int bucket = 0; bucket < energies.length; bucket++) { - energies[bucket] = mAccumulatedEnergiesMicroJoules[customBucketToIndex(bucket)]; + public @NonNull long[] getAccumulatedCustomBucketCharges() { + final long[] charges = new long[getNumberCustomPowerBuckets()]; + for (int bucket = 0; bucket < charges.length; bucket++) { + charges[bucket] = mAccumulatedChargeMicroCoulomb[customBucketToIndex(bucket)]; } - return energies; + return charges; } /** - * Map {@link android.view.Display} STATE_ to corresponding {@link StandardEnergyBucket}. + * Map {@link android.view.Display} STATE_ to corresponding {@link StandardPowerBucket}. */ - public static @StandardEnergyBucket int getDisplayEnergyBucket(int screenState) { + public static @StandardPowerBucket int getDisplayPowerBucket(int screenState) { if (Display.isOnState(screenState)) { - return ENERGY_BUCKET_SCREEN_ON; + return POWER_BUCKET_SCREEN_ON; } if (Display.isDozeState(screenState)) { - return ENERGY_BUCKET_SCREEN_DOZE; + return POWER_BUCKET_SCREEN_DOZE; } - return ENERGY_BUCKET_SCREEN_OTHER; + return POWER_BUCKET_SCREEN_OTHER; } /** @@ -280,9 +284,9 @@ public class MeasuredEnergyStats { // Check if any MeasuredEnergyStats exists on the parcel if (arraySize == 0) return null; - final int numCustomBuckets = arraySize - NUMBER_STANDARD_ENERGY_BUCKETS; + final int numCustomBuckets = arraySize - NUMBER_STANDARD_POWER_BUCKETS; final MeasuredEnergyStats stats = new MeasuredEnergyStats( - new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], numCustomBuckets); + new boolean[NUMBER_STANDARD_POWER_BUCKETS], numCustomBuckets); stats.readSummaryFromParcel(in, true); return stats; } @@ -337,8 +341,8 @@ public class MeasuredEnergyStats { /** Returns true iff any of the buckets are supported and non-zero. */ private boolean containsInterestingData() { - for (int index = 0; index < mAccumulatedEnergiesMicroJoules.length; index++) { - if (mAccumulatedEnergiesMicroJoules[index] > 0) return true; + for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) { + if (mAccumulatedChargeMicroCoulomb[index] > 0) return true; } return false; } @@ -359,7 +363,7 @@ public class MeasuredEnergyStats { stats.writeSummaryToParcel(dest, skipZero); } - /** Reset accumulated energy. */ + /** Reset accumulated charges. */ private void reset() { final int numIndices = getNumberOfIndices(); for (int index = 0; index < numIndices; index++) { @@ -367,42 +371,42 @@ public class MeasuredEnergyStats { } } - /** Reset accumulated energy of the given stats. */ + /** Reset accumulated charges of the given stats. */ public static void resetIfNotNull(@Nullable MeasuredEnergyStats stats) { if (stats != null) stats.reset(); } /** If the index is AVAILABLE, overwrite its value; otherwise leave it as UNAVAILABLE. */ private void setValueIfSupported(int index, long value) { - if (mAccumulatedEnergiesMicroJoules[index] != ENERGY_DATA_UNAVAILABLE) { - mAccumulatedEnergiesMicroJoules[index] = value; + if (mAccumulatedChargeMicroCoulomb[index] != POWER_DATA_UNAVAILABLE) { + mAccumulatedChargeMicroCoulomb[index] = value; } } /** - * Check if measuring the energy of the given bucket is supported by this device. - * @throws IllegalArgumentException if not a valid {@link StandardEnergyBucket}. + * Check if measuring the charge consumption of the given bucket is supported by this device. + * @throws IllegalArgumentException if not a valid {@link StandardPowerBucket}. */ - public boolean isStandardBucketSupported(@StandardEnergyBucket int bucket) { + public boolean isStandardBucketSupported(@StandardPowerBucket int bucket) { checkValidStandardBucket(bucket); return isIndexSupported(bucket); } private boolean isIndexSupported(int index) { - return mAccumulatedEnergiesMicroJoules[index] != ENERGY_DATA_UNAVAILABLE; + return mAccumulatedChargeMicroCoulomb[index] != POWER_DATA_UNAVAILABLE; } - /** Check if the supported energy buckets are precisely those given. */ + /** Check if the supported power buckets are precisely those given. */ public boolean isSupportEqualTo( @NonNull boolean[] queriedStandardBuckets, int numCustomBuckets) { final int numBuckets = getNumberOfIndices(); // TODO(b/178504428): Detect whether custom buckets have changed qualitatively, not just // quantitatively, and treat as mismatch if so. - if (numBuckets != NUMBER_STANDARD_ENERGY_BUCKETS + numCustomBuckets) { + if (numBuckets != NUMBER_STANDARD_POWER_BUCKETS + numCustomBuckets) { return false; } - for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_ENERGY_BUCKETS; stdBucket++) { + for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) { if (isStandardBucketSupported(stdBucket) != queriedStandardBuckets[stdBucket]) { return false; } @@ -413,14 +417,14 @@ public class MeasuredEnergyStats { /** Dump debug data. */ public void dump(PrintWriter pw) { pw.print(" "); - for (int index = 0; index < mAccumulatedEnergiesMicroJoules.length; index++) { + for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) { pw.print(getBucketName(index)); pw.print(" : "); - pw.print(mAccumulatedEnergiesMicroJoules[index]); + pw.print(mAccumulatedChargeMicroCoulomb[index]); if (!isIndexSupported(index)) { pw.print(" (unsupported)"); } - if (index != mAccumulatedEnergiesMicroJoules.length - 1) { + if (index != mAccumulatedChargeMicroCoulomb.length - 1) { pw.print(", "); } } @@ -433,38 +437,38 @@ public class MeasuredEnergyStats { */ private static String getBucketName(int index) { if (isValidStandardBucket(index)) { - return DebugUtils.valueToString(MeasuredEnergyStats.class, "ENERGY_BUCKET_", index); + return DebugUtils.valueToString(MeasuredEnergyStats.class, "POWER_BUCKET_", index); } return "CUSTOM_" + indexToCustomBucket(index); } - /** Get the number of custom energy buckets on this device. */ - public int getNumberCustomEnergyBuckets() { - return mAccumulatedEnergiesMicroJoules.length - NUMBER_STANDARD_ENERGY_BUCKETS; + /** Get the number of custom power buckets on this device. */ + public int getNumberCustomPowerBuckets() { + return mAccumulatedChargeMicroCoulomb.length - NUMBER_STANDARD_POWER_BUCKETS; } private static int customBucketToIndex(int customBucket) { - return customBucket + NUMBER_STANDARD_ENERGY_BUCKETS; + return customBucket + NUMBER_STANDARD_POWER_BUCKETS; } private static int indexToCustomBucket(int index) { - return index - NUMBER_STANDARD_ENERGY_BUCKETS; + return index - NUMBER_STANDARD_POWER_BUCKETS; } - private static void checkValidStandardBucket(@StandardEnergyBucket int bucket) { + private static void checkValidStandardBucket(@StandardPowerBucket int bucket) { if (!isValidStandardBucket(bucket)) { - throw new IllegalArgumentException("Illegal StandardEnergyBucket " + bucket); + throw new IllegalArgumentException("Illegal StandardPowerBucket " + bucket); } } - private static boolean isValidStandardBucket(@StandardEnergyBucket int bucket) { - return bucket >= 0 && bucket < NUMBER_STANDARD_ENERGY_BUCKETS; + private static boolean isValidStandardBucket(@StandardPowerBucket int bucket) { + return bucket >= 0 && bucket < NUMBER_STANDARD_POWER_BUCKETS; } /** Returns whether the given custom bucket is valid (exists) on this device. */ @VisibleForTesting public boolean isValidCustomBucket(int customBucket) { return customBucket >= 0 - && customBucketToIndex(customBucket) < mAccumulatedEnergiesMicroJoules.length; + && customBucketToIndex(customBucket) < mAccumulatedChargeMicroCoulomb.length; } } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index fde48e86b0f3..2e25ea3601da 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -79,7 +79,7 @@ interface IStatusBarService in int notificationLocation, boolean modifiedBeforeSending); void onNotificationSettingsViewed(String key); void onNotificationBubbleChanged(String key, boolean isBubble, int flags); - void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed); + void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, boolean isBubbleSuppressed); void hideCurrentInputMethodForBubbles(); void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName); void clearInlineReplyUriPermissions(String key); diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp index b0c575162b56..b207ad39edc3 100644 --- a/core/jni/android_content_res_ApkAssets.cpp +++ b/core/jni/android_content_res_ApkAssets.cpp @@ -353,14 +353,10 @@ static jlong NativeLoadEmpty(JNIEnv* env, jclass /*clazz*/, jint flags, jobject return reinterpret_cast<jlong>(apk_assets.release()); } -static void NativeDestroy(void* ptr) { +static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) { delete reinterpret_cast<ApkAssets*>(ptr); } -static jlong NativeGetFinalizer(JNIEnv* /*env*/, jclass /*clazz*/) { - return static_cast<jlong>(reinterpret_cast<uintptr_t>(&NativeDestroy)); -} - static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) { auto apk_assets = reinterpret_cast<const ApkAssets*>(ptr); if (auto path = apk_assets->GetPath()) { @@ -477,7 +473,7 @@ static const JNINativeMethod gApkAssetsMethods[] = { {"nativeLoadFdOffsets", "(ILjava/io/FileDescriptor;Ljava/lang/String;JJILandroid/content/res/loader/AssetsProvider;)J", (void*)NativeLoadFromFdOffset}, - {"nativeGetFinalizer", "()J", (void*)NativeGetFinalizer}, + {"nativeDestroy", "(J)V", (void*)NativeDestroy}, {"nativeGetAssetPath", "(J)Ljava/lang/String;", (void*)NativeGetAssetPath}, {"nativeGetDebugName", "(J)Ljava/lang/String;", (void*)NativeGetDebugName}, {"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock}, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4bbb69fdeb97..8e1da0819515 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1915,7 +1915,7 @@ @hide --> <permission android:name="android.permission.SUSPEND_APPS" - android:protectionLevel="signature|wellbeing" /> + android:protectionLevel="signature|role" /> <!-- Allows applications to discover and pair bluetooth devices. <p>Protection level: normal @@ -2789,7 +2789,7 @@ <p>Not for use by third-party applications. --> <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY" - android:protectionLevel="signature|recents|wellbeing"/> + android:protectionLevel="signature|recents|role"/> <!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND} @hide @@ -5138,7 +5138,7 @@ <!-- @SystemApi Allows the holder to access and manage instant applications on the device. @hide --> <permission android:name="android.permission.ACCESS_INSTANT_APPS" - android:protectionLevel="signature|installer|verifier|wellbeing" /> + android:protectionLevel="signature|installer|verifier|role" /> <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS"/> <!-- Allows the holder to view the instant applications on the device. @@ -5318,7 +5318,7 @@ <!-- @SystemApi Allows an application to turn on / off quiet mode. @hide --> <permission android:name="android.permission.MODIFY_QUIET_MODE" - android:protectionLevel="signature|privileged|wellbeing|development" /> + android:protectionLevel="signature|privileged|development" /> <!-- Allows internal management of the camera framework @hide --> @@ -5566,6 +5566,12 @@ <permission android:name="android.permission.RENOUNCE_PERMISSIONS" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Allows the holder to set the source of the data when setting a clip on the + clipboard. + @hide --> + <permission android:name="android.permission.SET_CLIP_SOURCE" + android:protectionLevel="signature|recents" /> + <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> <!-- Attribution for Country Detector. --> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index efc8fe9aafa2..05d29c2685f4 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -8633,6 +8633,9 @@ Described here are the attributes that can be included in that tag. --> <declare-styleable name="RecognitionService"> <attr name="settingsActivity" /> + <!-- Flag indicating whether a recognition service can be selected as default. The default + value of this flag is true. --> + <attr name="selectableAsDefault" format="boolean" /> </declare-styleable> <!-- Use <code>voice-interaction-service</code> as the root tag of the XML resource that diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index bed5c31bd327..aaa986b52c6a 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -285,9 +285,6 @@ <!-- Additional flag from base permission type: this permission can be automatically granted to the system default text classifier --> <flag name="textClassifier" value="0x10000" /> - <!-- Additional flag from base permission type: this permission will be granted to the - wellbeing app, as defined by the OEM. --> - <flag name="wellbeing" value="0x20000" /> <!-- Additional flag from base permission type: this permission can be automatically granted to the document manager --> <flag name="documenter" value="0x40000" /> @@ -1370,7 +1367,7 @@ <p>The default value of this attribute is <code>false</code>. --> <attr name="resumeWhilePausing" format="boolean" /> - <!-- Indicates that it is okay for this activity to be put in multi-window mode. Intended for a + <!-- Hint to platform that the activity works well in multi-window mode. Intended for a multi-window device where there can be multiple activities of various sizes on the screen at the same time. @@ -1390,7 +1387,7 @@ resizeable. <p>NOTE: The value of {@link android.R.attr#screenOrientation} is ignored for - resizeable activities when in multi-window mode. --> + resizeable activities when in multi-window mode before Android 12. --> <attr name="resizeableActivity" format="boolean" /> <!-- Indicates that the activity specifically supports the picture-in-picture form of diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index c00581f981af..22467e4c1402 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -171,7 +171,7 @@ <color name="accessibility_focus_highlight_color">#bf39b500</color> <color name="autofilled_highlight">#4dffeb3b</color> - <color name="system_notification_accent_color">#ff607D8B</color> + <color name="system_notification_accent_color">#00000000</color> <!-- Default user icon colors --> <color name="user_icon_1">#ff00bcd4</color><!-- cyan 500 --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 247ca16cc2f1..8bc3a52fa17b 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1959,6 +1959,8 @@ <string name="config_systemSpeechRecognizer" translatable="false"></string> <!-- The name of the package that will hold the system Wi-Fi coex manager role. --> <string name="config_systemWifiCoexManager" translateable="false"></string> + <!-- The name of the package that will hold the wellbeing role. --> + <string name="config_systemWellbeing" translatable="false"></string> <!-- The name of the package that will be allowed to change its components' label/icon. --> <string name="config_overrideComponentUiPackage" translatable="false"></string> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 7702ee437c43..b5d1e0ceec02 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3086,6 +3086,7 @@ <public name="hand_secondTintMode"/> <public name="dataExtractionRules"/> <public name="passwordsActivity"/> + <public name="selectableAsDefault"/> </public-group> <public-group type="drawable" first-id="0x010800b5"> @@ -3171,6 +3172,8 @@ <public name="config_systemSpeechRecognizer" /> <!-- @hide @SystemApi --> <public name="config_systemWifiCoexManager" /> + <!-- @hide @SystemApi --> + <public name="config_systemWellbeing" /> </public-group> <public-group type="id" first-id="0x01020055"> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java index 9e6827c19cb2..78569bdb4adc 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java @@ -38,14 +38,9 @@ public class BatteryConsumerData { private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER, PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI}; - // Temporary placeholder voltage for converting energy to charge - // TODO: remove this when b/173765509 is resolved - private static final double MOCK_NOMINAL_VOLTAGE = 3.7; - // Unit conversion: - // mAh = uWs * (1/1000)(milli/micro) * (1/Voltage) * (1/3600)(hours/second) - private static final double UJ_2_MAH = - (1.0 / 1000) * (1.0 / MOCK_NOMINAL_VOLTAGE) * (1.0 / 3600); + // mAh = uC * (1/1000)(milli/micro) * (1/3600)(hours/second) + private static final double UC_2_MAH = (1.0 / 1000) * (1.0 / 3600); enum EntryType { POWER, @@ -178,8 +173,10 @@ public class BatteryConsumerData { mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo( context.getPackageManager(), requestedBatterySipper); - long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy(); - long uidScreenMeasuredEnergyUJ = requestedBatterySipper.uidObj.getScreenOnEnergy(); + long totalScreenMeasuredChargeUC = + batteryStats.getScreenOnMeasuredBatteryConsumptionUC(); + long uidScreenMeasuredChargeUC = + requestedBatterySipper.uidObj.getScreenOnMeasuredBatteryConsumptionUC(); addEntry("Total power", EntryType.POWER, requestedBatterySipper.totalSmearedPowerMah, totalSmearedPowerMah); @@ -189,10 +186,10 @@ public class BatteryConsumerData { requestedBatterySipper.totalSmearedPowerMah, totalPowerExcludeSystemMah); addEntry("Screen, smeared", EntryType.POWER, requestedBatterySipper.screenPowerMah, totalScreenPower); - if (uidScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE - && totalScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) { - final double measuredCharge = UJ_2_MAH * uidScreenMeasuredEnergyUJ; - final double totalMeasuredCharge = UJ_2_MAH * totalScreenMeasuredEnergyUJ; + if (uidScreenMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE + && totalScreenMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) { + final double measuredCharge = UC_2_MAH * uidScreenMeasuredChargeUC; + final double totalMeasuredCharge = UC_2_MAH * totalScreenMeasuredChargeUC; addEntry("Screen, measured", EntryType.POWER, measuredCharge, totalMeasuredCharge); } @@ -297,17 +294,19 @@ public class BatteryConsumerData { BatteryStats batteryStats) { switch (drainType) { case AMBIENT_DISPLAY: - final long totalDozeMeasuredEnergyUJ = batteryStats.getScreenDozeEnergy(); - if (totalDozeMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) { - final double measuredCharge = UJ_2_MAH * totalDozeMeasuredEnergyUJ; + final long totalDozeMeasuredChargeUC = + batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(); + if (totalDozeMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) { + final double measuredCharge = UC_2_MAH * totalDozeMeasuredChargeUC; addEntry("Measured ambient display power", EntryType.POWER, measuredCharge, measuredCharge); } break; case SCREEN: - final long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy(); - if (totalScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) { - final double measuredCharge = UJ_2_MAH * totalScreenMeasuredEnergyUJ; + final long totalScreenMeasuredChargeUC = + batteryStats.getScreenOnMeasuredBatteryConsumptionUC(); + if (totalScreenMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) { + final double measuredCharge = UC_2_MAH * totalScreenMeasuredChargeUC; addEntry("Measured screen power", EntryType.POWER, measuredCharge, measuredCharge); } diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java index 7e1e7f4bdd7f..ab24f89015c7 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java @@ -33,6 +33,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import java.util.Arrays; +import java.util.List; + /** * Tests for AccessibilityInteractionClient */ @@ -62,7 +65,7 @@ public class AccessibilityInteractionClientTest { final long accessibilityNodeId = 0x4321L; AccessibilityNodeInfo nodeFromConnection = AccessibilityNodeInfo.obtain(); nodeFromConnection.setSourceNodeId(accessibilityNodeId, windowId); - mMockConnection.mInfoToReturn = nodeFromConnection; + mMockConnection.mInfosToReturn = Arrays.asList(nodeFromConnection); AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); AccessibilityNodeInfo node = client.findAccessibilityNodeInfoByAccessibilityId( MOCK_CONNECTION_ID, windowId, accessibilityNodeId, true, 0, null); @@ -72,7 +75,7 @@ public class AccessibilityInteractionClientTest { } private static class MockConnection extends AccessibilityServiceConnectionImpl { - AccessibilityNodeInfo mInfoToReturn; + List<AccessibilityNodeInfo> mInfosToReturn; @Override public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, @@ -80,7 +83,7 @@ public class AccessibilityInteractionClientTest { IAccessibilityInteractionConnectionCallback callback, int flags, long threadId, Bundle arguments) { try { - callback.setFindAccessibilityNodeInfoResult(mInfoToReturn, interactionId); + callback.setFindAccessibilityNodeInfosResult(mInfosToReturn, interactionId); } catch (RemoteException e) { throw new RuntimeException(e); } diff --git a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java index add04698e372..c67f90136992 100644 --- a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java @@ -44,18 +44,18 @@ public class AmbientDisplayPowerCalculatorTest { public void testMeasuredEnergyBasedModel() { BatteryStatsImpl stats = mStatsRule.getBatteryStats(); - stats.updateDisplayEnergyLocked(300_000_000, Display.STATE_ON, 0); + stats.updateDisplayMeasuredEnergyStatsLocked(300_000_000, Display.STATE_ON, 0); stats.noteScreenStateLocked(Display.STATE_DOZE, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS); - stats.updateDisplayEnergyLocked(200_000_000, Display.STATE_DOZE, + stats.updateDisplayMeasuredEnergyStatsLocked(200_000_000, Display.STATE_DOZE, 30 * MINUTE_IN_MS); stats.noteScreenStateLocked(Display.STATE_OFF, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS); - stats.updateDisplayEnergyLocked(100_000_000, Display.STATE_OFF, + stats.updateDisplayMeasuredEnergyStatsLocked(100_000_000, Display.STATE_OFF, 120 * MINUTE_IN_MS); AmbientDisplayPowerCalculator calculator = @@ -68,8 +68,9 @@ public class AmbientDisplayPowerCalculatorTest { SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY); assertThat(consumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE)) .isEqualTo(90 * MINUTE_IN_MS); + // 100,000,00 uC / 1000 (micro-/milli-) / 360 (seconds/hour) = 27.777778 mAh assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE)) - .isWithin(PRECISION).of(7.5075075); + .isWithin(PRECISION).of(27.777778); } @Test diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java index ff728d651067..4319740ffdf3 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java @@ -121,7 +121,7 @@ public class BatteryStatsCpuTimesTest { when(mCpuUidFreqTimeReader.readFreqs(mPowerProfile)).thenReturn(freqs); // RUN - mBatteryStatsImpl.updateCpuTimeLocked(false, false); + mBatteryStatsImpl.updateCpuTimeLocked(false, false, null); // VERIFY assertArrayEquals("Unexpected cpu freqs", freqs, mBatteryStatsImpl.getCpuFreqs()); @@ -141,7 +141,7 @@ public class BatteryStatsCpuTimesTest { mBatteryStatsImpl.setOnBatteryInternal(true); // RUN - mBatteryStatsImpl.updateCpuTimeLocked(true, false); + mBatteryStatsImpl.updateCpuTimeLocked(true, false, null); // VERIFY verify(mUserInfoProvider).refreshUserIds(); @@ -221,7 +221,7 @@ public class BatteryStatsCpuTimesTest { } // RUN - mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids, true); + mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids, true, null); // VERIFY int totalClustersTimeMs = 0; @@ -563,7 +563,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -596,7 +596,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -647,7 +647,7 @@ public class BatteryStatsCpuTimesTest { when(mCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(true); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -690,7 +690,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -757,7 +757,7 @@ public class BatteryStatsCpuTimesTest { when(mCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(true); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers, true, false); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers, true, false, null); // VERIFY final long[][] expectedWakeLockUidTimesUs = new long[clusterFreqs.length][]; @@ -846,7 +846,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -879,7 +879,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -923,7 +923,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -963,7 +963,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1020,7 +1020,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1169,7 +1169,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidClusterTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true); + mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1199,7 +1199,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidClusterTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true); + mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1244,7 +1244,7 @@ public class BatteryStatsCpuTimesTest { any(KernelCpuUidClusterTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true); + mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true, null); // VERIFY for (int i = 0; i < testUids.length; ++i) { diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index 931611ea7478..f168b3c160cb 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -503,7 +503,7 @@ public class BatteryStatsNoteTest extends TestCase { } @SmallTest - public void testUpdateDisplayEnergyLocked() { + public void testUpdateDisplayMeasuredEnergyStatsLocked() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); @@ -520,8 +520,8 @@ public class BatteryStatsNoteTest extends TestCase { // Case A: uid1 off, uid2 off, battery off, screen off bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0); bi.setOnBatteryInternal(battery); - bi.updateDisplayEnergyLocked(500_000, screen, clocks.realtime); - checkMeasuredEnergy("A", uid1, blame1, uid2, blame2, globalDoze, bi); + bi.updateDisplayMeasuredEnergyStatsLocked(500_000, screen, clocks.realtime); + checkMeasuredCharge("A", uid1, blame1, uid2, blame2, globalDoze, bi); // Case B: uid1 off, uid2 off, battery ON, screen off clocks.realtime += 17; @@ -529,65 +529,65 @@ public class BatteryStatsNoteTest extends TestCase { bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0); bi.setOnBatteryInternal(battery); clocks.realtime += 19; - bi.updateDisplayEnergyLocked(510_000, screen, clocks.realtime); - checkMeasuredEnergy("B", uid1, blame1, uid2, blame2, globalDoze, bi); + bi.updateDisplayMeasuredEnergyStatsLocked(510_000, screen, clocks.realtime); + checkMeasuredCharge("B", uid1, blame1, uid2, blame2, globalDoze, bi); // Case C: uid1 ON, uid2 off, battery on, screen off clocks.realtime += 18; setFgState(uid1, true, bi); clocks.realtime += 18; - bi.updateDisplayEnergyLocked(520_000, screen, clocks.realtime); - checkMeasuredEnergy("C", uid1, blame1, uid2, blame2, globalDoze, bi); + bi.updateDisplayMeasuredEnergyStatsLocked(520_000, screen, clocks.realtime); + checkMeasuredCharge("C", uid1, blame1, uid2, blame2, globalDoze, bi); // Case D: uid1 on, uid2 off, battery on, screen ON clocks.realtime += 17; screen = Display.STATE_ON; - bi.updateDisplayEnergyLocked(521_000, screen, clocks.realtime); + bi.updateDisplayMeasuredEnergyStatsLocked(521_000, screen, clocks.realtime); blame1 += 0; // Screen had been off during the measurement period - checkMeasuredEnergy("D.1", uid1, blame1, uid2, blame2, globalDoze, bi); + checkMeasuredCharge("D.1", uid1, blame1, uid2, blame2, globalDoze, bi); clocks.realtime += 101; - bi.updateDisplayEnergyLocked(530_000, screen, clocks.realtime); + bi.updateDisplayMeasuredEnergyStatsLocked(530_000, screen, clocks.realtime); blame1 += 530_000; - checkMeasuredEnergy("D.2", uid1, blame1, uid2, blame2, globalDoze, bi); + checkMeasuredCharge("D.2", uid1, blame1, uid2, blame2, globalDoze, bi); // Case E: uid1 on, uid2 ON, battery on, screen on clocks.realtime += 20; setFgState(uid2, true, bi); clocks.realtime += 40; - bi.updateDisplayEnergyLocked(540_000, screen, clocks.realtime); + bi.updateDisplayMeasuredEnergyStatsLocked(540_000, screen, clocks.realtime); // In the past 60ms, sum of fg is 20+40+40=100ms. uid1 is blamed for 60/100; uid2 for 40/100 blame1 += 540_000 * (20 + 40) / (20 + 40 + 40); blame2 += 540_000 * ( 0 + 40) / (20 + 40 + 40); - checkMeasuredEnergy("E", uid1, blame1, uid2, blame2, globalDoze, bi); + checkMeasuredCharge("E", uid1, blame1, uid2, blame2, globalDoze, bi); // Case F: uid1 on, uid2 OFF, battery on, screen on clocks.realtime += 40; setFgState(uid2, false, bi); clocks.realtime += 120; - bi.updateDisplayEnergyLocked(550_000, screen, clocks.realtime); + bi.updateDisplayMeasuredEnergyStatsLocked(550_000, screen, clocks.realtime); // In the past 160ms, sum f fg is 200ms. uid1 is blamed for 40+120 of it; uid2 for 40 of it. blame1 += 550_000 * (40 + 120) / (40 + 40 + 120); blame2 += 550_000 * (40 + 0 ) / (40 + 40 + 120); - checkMeasuredEnergy("F", uid1, blame1, uid2, blame2, globalDoze, bi); + checkMeasuredCharge("F", uid1, blame1, uid2, blame2, globalDoze, bi); // Case G: uid1 on, uid2 off, battery on, screen DOZE clocks.realtime += 5; screen = Display.STATE_DOZE; - bi.updateDisplayEnergyLocked(570_000, screen, clocks.realtime); + bi.updateDisplayMeasuredEnergyStatsLocked(570_000, screen, clocks.realtime); blame1 += 570_000; // All of this pre-doze time is blamed on uid1. - checkMeasuredEnergy("G", uid1, blame1, uid2, blame2, globalDoze, bi); + checkMeasuredCharge("G", uid1, blame1, uid2, blame2, globalDoze, bi); // Case H: uid1 on, uid2 off, battery on, screen ON clocks.realtime += 6; screen = Display.STATE_ON; - bi.updateDisplayEnergyLocked(580_000, screen, clocks.realtime); + bi.updateDisplayMeasuredEnergyStatsLocked(580_000, screen, clocks.realtime); blame1 += 0; // The screen had been doze during the energy period globalDoze += 580_000; - checkMeasuredEnergy("H", uid1, blame1, uid2, blame2, globalDoze, bi); + checkMeasuredCharge("H", uid1, blame1, uid2, blame2, globalDoze, bi); } @SmallTest - public void testUpdateCustomMeasuredEnergyDataLocked_neverCalled() { + public void testUpdateCustomMeasuredEnergyStatsLocked_neverCalled() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); bi.setOnBatteryInternal(true); @@ -595,20 +595,20 @@ public class BatteryStatsNoteTest extends TestCase { final int uid1 = 11500; final int uid2 = 11501; - // Initially, all custom buckets report energy of 0. - checkCustomMeasuredEnergy("0", 0, 0, uid1, 0, 0, uid2, 0, 0, bi); + // Initially, all custom buckets report charge of 0. + checkCustomBatteryConsumption("0", 0, 0, uid1, 0, 0, uid2, 0, 0, bi); } @SmallTest - public void testUpdateCustomMeasuredEnergyDataLocked() { + public void testUpdateCustomMeasuredEnergyStatsLocked() { final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); final int bucketA = 0; // Custom bucket 0 final int bucketB = 1; // Custom bucket 1 - long totalBlameA = 0; // Total energy consumption for bucketA (may exceed sum of uids) - long totalBlameB = 0; // Total energy consumption for bucketB (may exceed sum of uids) + long totalBlameA = 0; // Total charge consumption for bucketA (may exceed sum of uids) + long totalBlameB = 0; // Total charge consumption for bucketB (may exceed sum of uids) final int uid1 = 10500; long blame1A = 0; // Blame for uid1 in bucketA @@ -618,60 +618,60 @@ public class BatteryStatsNoteTest extends TestCase { long blame2A = 0; // Blame for uid2 in bucketA long blame2B = 0; // Blame for uid2 in bucketB - final SparseLongArray newEnergiesA = new SparseLongArray(2); - final SparseLongArray newEnergiesB = new SparseLongArray(2); + final SparseLongArray newChargesA = new SparseLongArray(2); + final SparseLongArray newChargesB = new SparseLongArray(2); // ----- Case A: battery off (so blame does not increase) bi.setOnBatteryInternal(false); - newEnergiesA.put(uid1, 20_000); - // Implicit newEnergiesA.put(uid2, 0); - bi.updateCustomMeasuredEnergyDataLocked(bucketA, 500_000, newEnergiesA); + newChargesA.put(uid1, 20_000); + // Implicit newChargesA.put(uid2, 0); + bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 500_000, newChargesA); - newEnergiesB.put(uid1, 60_000); - // Implicit newEnergiesB.put(uid2, 0); - bi.updateCustomMeasuredEnergyDataLocked(bucketB, 700_000, newEnergiesB); + newChargesB.put(uid1, 60_000); + // Implicit newChargesB.put(uid2, 0); + bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 700_000, newChargesB); - checkCustomMeasuredEnergy( + checkCustomBatteryConsumption( "A", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi); // ----- Case B: battery on bi.setOnBatteryInternal(true); - newEnergiesA.put(uid1, 7_000); blame1A += 7_000; - // Implicit newEnergiesA.put(uid2, 0); blame2A += 0; - bi.updateCustomMeasuredEnergyDataLocked(bucketA, 310_000, newEnergiesA); + newChargesA.put(uid1, 7_000); blame1A += 7_000; + // Implicit newChargesA.put(uid2, 0); blame2A += 0; + bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 310_000, newChargesA); totalBlameA += 310_000; - newEnergiesB.put(uid1, 63_000); blame1B += 63_000; - newEnergiesB.put(uid2, 15_000); blame2B += 15_000; - bi.updateCustomMeasuredEnergyDataLocked(bucketB, 790_000, newEnergiesB); + newChargesB.put(uid1, 63_000); blame1B += 63_000; + newChargesB.put(uid2, 15_000); blame2B += 15_000; + bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 790_000, newChargesB); totalBlameB += 790_000; - checkCustomMeasuredEnergy( + checkCustomBatteryConsumption( "B", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi); // ----- Case C: battery still on - newEnergiesA.delete(uid1); blame1A += 0; - newEnergiesA.put(uid2, 16_000); blame2A += 16_000; - bi.updateCustomMeasuredEnergyDataLocked(bucketA, 560_000, newEnergiesA); + newChargesA.delete(uid1); blame1A += 0; + newChargesA.put(uid2, 16_000); blame2A += 16_000; + bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 560_000, newChargesA); totalBlameA += 560_000; - bi.updateCustomMeasuredEnergyDataLocked(bucketB, 10_000, null); + bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 10_000, null); totalBlameB += 10_000; - checkCustomMeasuredEnergy( + checkCustomBatteryConsumption( "C", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi); // ----- Case D: battery still on - bi.updateCustomMeasuredEnergyDataLocked(bucketA, 0, newEnergiesA); - bi.updateCustomMeasuredEnergyDataLocked(bucketB, 15_000, new SparseLongArray(1)); + bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 0, newChargesA); + bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 15_000, new SparseLongArray(1)); totalBlameB += 15_000; - checkCustomMeasuredEnergy( + checkCustomBatteryConsumption( "D", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi); } @@ -686,32 +686,34 @@ public class BatteryStatsNoteTest extends TestCase { } } - private void checkMeasuredEnergy(String caseName, int uid1, long blame1, int uid2, long blame2, + private void checkMeasuredCharge(String caseName, int uid1, long blame1, int uid2, long blame2, long globalDoze, MockBatteryStatsImpl bi) { - final int bucket = MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON; + final int bucket = MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON; assertEquals("Wrong uid1 blame for Case " + caseName, blame1, - bi.getUidStatsLocked(uid1).getMeasuredEnergyMicroJoules(bucket)); + bi.getUidStatsLocked(uid1).getMeasuredBatteryConsumptionUC(bucket)); assertEquals("Wrong uid2 blame for Case " + caseName, blame2, - bi.getUidStatsLocked(uid2).getMeasuredEnergyMicroJoules(bucket)); + bi.getUidStatsLocked(uid2).getMeasuredBatteryConsumptionUC(bucket)); assertEquals("Wrong total blame for Case " + caseName, blame1 + blame2, - bi.getScreenOnEnergy()); + bi.getScreenOnMeasuredBatteryConsumptionUC()); assertEquals("Wrong doze for Case " + caseName, globalDoze, - bi.getScreenDozeEnergy()); + bi.getScreenDozeMeasuredBatteryConsumptionUC()); } - private void checkCustomMeasuredEnergy(String caseName, + private void checkCustomBatteryConsumption(String caseName, long totalBlameA, long totalBlameB, int uid1, long blame1A, long blame1B, int uid2, long blame2A, long blame2B, MockBatteryStatsImpl bi) { - final long[] actualTotal = bi.getCustomMeasuredEnergiesMicroJoules(); - final long[] actualUid1 = bi.getUidStatsLocked(uid1).getCustomMeasuredEnergiesMicroJoules(); - final long[] actualUid2 = bi.getUidStatsLocked(uid2).getCustomMeasuredEnergiesMicroJoules(); + final long[] actualTotal = bi.getCustomConsumerMeasuredBatteryConsumptionUC(); + final long[] actualUid1 = + bi.getUidStatsLocked(uid1).getCustomConsumerMeasuredBatteryConsumptionUC(); + final long[] actualUid2 = + bi.getUidStatsLocked(uid2).getCustomConsumerMeasuredBatteryConsumptionUC(); assertNotNull(actualTotal); assertNotNull(actualUid1); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java index 167994200ed7..8aeb761ffc4d 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java @@ -147,7 +147,7 @@ public class BatteryUsageStatsRule implements TestRule { BatteryUsageStats apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) { final long[] customMeasuredEnergiesMicroJoules = - mBatteryStats.getCustomMeasuredEnergiesMicroJoules(); + mBatteryStats.getCustomConsumerMeasuredBatteryConsumptionUC(); final int customMeasuredEnergiesCount = customMeasuredEnergiesMicroJoules != null ? customMeasuredEnergiesMicroJoules.length : 0; diff --git a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java index e691beb09a70..70888905d7c8 100644 --- a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java @@ -126,7 +126,7 @@ public class CpuPowerCalculatorTest { return null; }).when(mMockKernelCpuUidClusterTimeReader).readDelta(any()); - mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true); + mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, null); mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("foo").addCpuTimeLocked(4321, 1234); mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("bar").addCpuTimeLocked(5432, 2345); diff --git a/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java index f298f5988fc3..0c91b2959f8e 100644 --- a/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java @@ -47,10 +47,10 @@ public class CustomMeasuredPowerCalculatorTest { final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); SparseLongArray uidEnergies = new SparseLongArray(); uidEnergies.put(APP_UID, 30_000_000); - batteryStats.updateCustomMeasuredEnergyDataLocked(0, 100_000_000, uidEnergies); + batteryStats.updateCustomMeasuredEnergyStatsLocked(0, 100_000_000, uidEnergies); uidEnergies.put(APP_UID, 120_000_000); - batteryStats.updateCustomMeasuredEnergyDataLocked(1, 200_000_000, uidEnergies); + batteryStats.updateCustomMeasuredEnergyStatsLocked(1, 200_000_000, uidEnergies); CustomMeasuredPowerCalculator calculator = new CustomMeasuredPowerCalculator(mStatsRule.getPowerProfile()); diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java index 1687a78c9875..a47c4d832083 100644 --- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java @@ -47,8 +47,8 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { setExternalStatsSyncLocked(new DummyExternalStatsSync()); - final boolean[] supportedStandardBuckets - = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = + new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; Arrays.fill(supportedStandardBuckets, true); mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedStandardBuckets, 2); diff --git a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java index 86e615c035c7..f3cf81ca3e86 100644 --- a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java @@ -52,19 +52,19 @@ public class ScreenPowerCalculatorTest { BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); batteryStats.noteScreenStateLocked(Display.STATE_ON, 0, 0, 0); - batteryStats.updateDisplayEnergyLocked(0, Display.STATE_ON, 2 * MINUTE_IN_MS); + batteryStats.updateDisplayMeasuredEnergyStatsLocked(0, Display.STATE_ON, 2 * MINUTE_IN_MS); setFgState(APP_UID1, true, 2 * MINUTE_IN_MS, 2 * MINUTE_IN_MS); setFgState(APP_UID1, false, 20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS); setFgState(APP_UID2, true, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS); - batteryStats.updateDisplayEnergyLocked(300_000_000, Display.STATE_ON, + batteryStats.updateDisplayMeasuredEnergyStatsLocked(300_000_000, Display.STATE_ON, 60 * MINUTE_IN_MS); batteryStats.noteScreenStateLocked(Display.STATE_OFF, 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS); - batteryStats.updateDisplayEnergyLocked(100_000_000, Display.STATE_DOZE, + batteryStats.updateDisplayMeasuredEnergyStatsLocked(100_000_000, Display.STATE_DOZE, 120 * MINUTE_IN_MS); mStatsRule.setTime(120 * MINUTE_IN_US, 120 * MINUTE_IN_US); @@ -78,20 +78,29 @@ public class ScreenPowerCalculatorTest { mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_SCREEN); assertThat(consumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE)) .isEqualTo(80 * MINUTE_IN_MS); + + // 400000000 uAs * (1 mA / 1000 uA) * (1 h / 3600 s) = 111.11111 mAh assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE)) - .isWithin(PRECISION).of(30.03003); + .isWithin(PRECISION).of(111.11111); UidBatteryConsumer uid1 = mStatsRule.getUidBatteryConsumer(APP_UID1); assertThat(uid1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN)) .isEqualTo(18 * MINUTE_IN_MS); + + // Uid1 ran for 18 minutes out of the total 48 min of foreground time during the first + // Display update. Uid1 charge = 18 / 48 * 300000000 uAs = 31.25 mAh assertThat(uid1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isWithin(PRECISION).of(8.44594); + .isWithin(PRECISION).of(31.25); UidBatteryConsumer uid2 = mStatsRule.getUidBatteryConsumer(APP_UID2); assertThat(uid2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN)) .isEqualTo(90 * MINUTE_IN_MS); + + // Uid2 ran for 30 minutes out of the total 48 min of foreground time during the first + // Display update and then took all of the time during the second Display update. + // Uid1 charge = 30 / 48 * 300000000 + 100000000 mAs = 79.86111 mAh assertThat(uid2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN)) - .isWithin(PRECISION).of(21.58408); + .isWithin(PRECISION).of(79.86111); } @Test diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java index b5282e9a625a..6edbbb0ad789 100644 --- a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java @@ -91,7 +91,7 @@ public class SystemServicePowerCalculatorTest { new long[] {10000, 20000, 30000, 40000} ); - mMockBatteryStats.readKernelUidCpuFreqTimesLocked(null, true, false); + mMockBatteryStats.readKernelUidCpuFreqTimesLocked(null, true, false, null); int workSourceUid1 = 100; int workSourceUid2 = 200; diff --git a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java index d217bce24b9c..ed6e27b199b9 100644 --- a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java @@ -16,12 +16,12 @@ package com.android.internal.power; -import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE; +import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; -import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE; -import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON; -import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_OTHER; -import static com.android.internal.power.MeasuredEnergyStats.NUMBER_STANDARD_ENERGY_BUCKETS; +import static com.android.internal.power.MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS; +import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE; +import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON; +import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_OTHER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -48,75 +48,75 @@ public class MeasuredEnergyStatsTest { @Test public void testConstruction() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { if (supportedStandardBuckets[i]) { assertTrue(stats.isStandardBucketSupported(i)); - assertEquals(0L, stats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(0L, stats.getAccumulatedStandardBucketCharge(i)); } else { assertFalse(stats.isStandardBucketSupported(i)); - assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(POWER_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketCharge(i)); } } for (int i = 0; i < numCustomBuckets; i++) { - assertEquals(0L, stats.getAccumulatedCustomBucketEnergy(i)); + assertEquals(0L, stats.getAccumulatedCustomBucketCharge(i)); } } @Test public void testCreateFromTemplate() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats); - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { if (supportedStandardBuckets[i]) { assertTrue(newStats.isStandardBucketSupported(i)); - assertEquals(0L, newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i)); } else { assertFalse(newStats.isStandardBucketSupported(i)); - assertEquals(ENERGY_DATA_UNAVAILABLE, - newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(POWER_DATA_UNAVAILABLE, + newStats.getAccumulatedStandardBucketCharge(i)); } } for (int i = 0; i < numCustomBuckets; i++) { - assertEquals(0L, newStats.getAccumulatedCustomBucketEnergy(i)); + assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(i)); } } @Test public void testReadWriteParcel() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); @@ -126,32 +126,32 @@ public class MeasuredEnergyStatsTest { parcel.setDataPosition(0); MeasuredEnergyStats newStats = new MeasuredEnergyStats(parcel); - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { - assertEquals(stats.getAccumulatedStandardBucketEnergy(i), - newStats.getAccumulatedStandardBucketEnergy(i)); + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { + assertEquals(stats.getAccumulatedStandardBucketCharge(i), + newStats.getAccumulatedStandardBucketCharge(i)); } for (int i = 0; i < numCustomBuckets; i++) { - assertEquals(stats.getAccumulatedCustomBucketEnergy(i), - newStats.getAccumulatedCustomBucketEnergy(i)); + assertEquals(stats.getAccumulatedCustomBucketCharge(i), + newStats.getAccumulatedCustomBucketCharge(i)); } - assertEquals(ENERGY_DATA_UNAVAILABLE, - newStats.getAccumulatedCustomBucketEnergy(numCustomBuckets + 1)); + assertEquals(POWER_DATA_UNAVAILABLE, + newStats.getAccumulatedCustomBucketCharge(numCustomBuckets + 1)); parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); @@ -160,90 +160,90 @@ public class MeasuredEnergyStatsTest { parcel.setDataPosition(0); MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel); - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { assertEquals(stats.isStandardBucketSupported(i), newStats.isStandardBucketSupported(i)); - assertEquals(stats.getAccumulatedStandardBucketEnergy(i), - newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(stats.getAccumulatedStandardBucketCharge(i), + newStats.getAccumulatedStandardBucketCharge(i)); } for (int i = 0; i < numCustomBuckets; i++) { - assertEquals(stats.getAccumulatedCustomBucketEnergy(i), - newStats.getAccumulatedCustomBucketEnergy(i)); + assertEquals(stats.getAccumulatedCustomBucketCharge(i), + newStats.getAccumulatedCustomBucketCharge(i)); } - assertEquals(ENERGY_DATA_UNAVAILABLE, - newStats.getAccumulatedCustomBucketEnergy(numCustomBuckets + 1)); + assertEquals(POWER_DATA_UNAVAILABLE, + newStats.getAccumulatedCustomBucketCharge(numCustomBuckets + 1)); parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel_existingTemplate() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats template - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); - template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats template = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); template.updateCustomBucket(0, 50); final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 7); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 63); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 7); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 63); stats.updateCustomBucket(0, 315); stats.updateCustomBucket(1, 316); final Parcel parcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false); - final boolean[] newsupportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; - newsupportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - newsupportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched false > true - newsupportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true > false - final MeasuredEnergyStats newTemplate - = new MeasuredEnergyStats(newsupportedStandardBuckets, numCustomBuckets); + final boolean[] newsupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; + newsupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + newsupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true + newsupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false + final MeasuredEnergyStats newTemplate = + new MeasuredEnergyStats(newsupportedStandardBuckets, numCustomBuckets); parcel.setDataPosition(0); final MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate); - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { if (!newsupportedStandardBuckets[i]) { assertFalse(newStats.isStandardBucketSupported(i)); - assertEquals(ENERGY_DATA_UNAVAILABLE, - newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(POWER_DATA_UNAVAILABLE, + newStats.getAccumulatedStandardBucketCharge(i)); } else if (!supportedStandardBuckets[i]) { assertTrue(newStats.isStandardBucketSupported(i)); - assertEquals(0L, newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i)); } else { assertTrue(newStats.isStandardBucketSupported(i)); - assertEquals(stats.getAccumulatedStandardBucketEnergy(i), - newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(stats.getAccumulatedStandardBucketCharge(i), + newStats.getAccumulatedStandardBucketCharge(i)); } } for (int i = 0; i < numCustomBuckets; i++) { - assertEquals(stats.getAccumulatedCustomBucketEnergy(i), - newStats.getAccumulatedCustomBucketEnergy(i)); + assertEquals(stats.getAccumulatedCustomBucketCharge(i), + newStats.getAccumulatedCustomBucketCharge(i)); } - assertEquals(ENERGY_DATA_UNAVAILABLE, - newStats.getAccumulatedCustomBucketEnergy(numCustomBuckets + 1)); + assertEquals(POWER_DATA_UNAVAILABLE, + newStats.getAccumulatedCustomBucketCharge(numCustomBuckets + 1)); parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel_skipZero() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; Arrays.fill(supportedStandardBuckets, true); - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - // Accumulate energy in one bucket and one custom bucket, the rest should be zero - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200); + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + // Accumulate charge in one bucket and one custom bucket, the rest should be zero + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200); stats.updateCustomBucket(1, 60); // Let's try parcelling with including zeros @@ -254,20 +254,20 @@ public class MeasuredEnergyStatsTest { MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel( includeZerosParcel); - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { - if (i == ENERGY_BUCKET_SCREEN_ON) { + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { + if (i == POWER_BUCKET_SCREEN_ON) { assertEquals(stats.isStandardBucketSupported(i), newStats.isStandardBucketSupported(i)); - assertEquals(stats.getAccumulatedStandardBucketEnergy(i), - newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(stats.getAccumulatedStandardBucketCharge(i), + newStats.getAccumulatedStandardBucketCharge(i)); } else { assertTrue(newStats.isStandardBucketSupported(i)); - assertEquals(0L, newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i)); } } - assertEquals(0L, newStats.getAccumulatedCustomBucketEnergy(0)); - assertEquals(stats.getAccumulatedCustomBucketEnergy(1), - newStats.getAccumulatedCustomBucketEnergy(1)); + assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0)); + assertEquals(stats.getAccumulatedCustomBucketCharge(1), + newStats.getAccumulatedCustomBucketCharge(1)); includeZerosParcel.recycle(); // Now let's try parcelling with skipping zeros @@ -277,37 +277,37 @@ public class MeasuredEnergyStatsTest { newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(skipZerosParcel); - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { - if (i == ENERGY_BUCKET_SCREEN_ON) { + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { + if (i == POWER_BUCKET_SCREEN_ON) { assertEquals(stats.isStandardBucketSupported(i), newStats.isStandardBucketSupported(i)); - assertEquals(stats.getAccumulatedStandardBucketEnergy(i), - newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(stats.getAccumulatedStandardBucketCharge(i), + newStats.getAccumulatedStandardBucketCharge(i)); } else { assertFalse(newStats.isStandardBucketSupported(i)); - assertEquals(ENERGY_DATA_UNAVAILABLE, - newStats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(POWER_DATA_UNAVAILABLE, + newStats.getAccumulatedStandardBucketCharge(i)); } } - assertEquals(0L, newStats.getAccumulatedCustomBucketEnergy(0)); - assertEquals(stats.getAccumulatedCustomBucketEnergy(1), - newStats.getAccumulatedCustomBucketEnergy(1)); + assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0)); + assertEquals(stats.getAccumulatedCustomBucketCharge(1), + newStats.getAccumulatedCustomBucketCharge(1)); skipZerosParcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel_nullTemplate() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); @@ -315,40 +315,40 @@ public class MeasuredEnergyStatsTest { MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false); parcel.setDataPosition(0); - MeasuredEnergyStats newStats - = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, null); + MeasuredEnergyStats newStats = + MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, null); assertNull(newStats); parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel_boring() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats template - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); - template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats template = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); template.updateCustomBucket(0, 50); final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 0L); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 7L); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 0L); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 7L); final Parcel parcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false); - final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; - newSupportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - newSupportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched false > true - newSupportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true > false - final MeasuredEnergyStats newTemplate - = new MeasuredEnergyStats(newSupportedStandardBuckets, numCustomBuckets); + final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; + newSupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + newSupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true + newSupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false + final MeasuredEnergyStats newTemplate = + new MeasuredEnergyStats(newSupportedStandardBuckets, numCustomBuckets); parcel.setDataPosition(0); final MeasuredEnergyStats newStats = @@ -361,35 +361,35 @@ public class MeasuredEnergyStatsTest { @Test public void testUpdateBucket() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_DOZE, 30); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_DOZE, 30); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); stats.updateCustomBucket(0, 3); - assertEquals(15, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_ON)); - assertEquals(ENERGY_DATA_UNAVAILABLE, - stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_DOZE)); - assertEquals(40, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_OTHER)); - assertEquals(50 + 3, stats.getAccumulatedCustomBucketEnergy(0)); - assertEquals(60, stats.getAccumulatedCustomBucketEnergy(1)); + assertEquals(15, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON)); + assertEquals(POWER_DATA_UNAVAILABLE, + stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_DOZE)); + assertEquals(40, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER)); + assertEquals(50 + 3, stats.getAccumulatedCustomBucketCharge(0)); + assertEquals(60, stats.getAccumulatedCustomBucketCharge(1)); } @Test public void testIsValidCustomBucket() { - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 3); + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], 3); assertFalse(stats.isValidCustomBucket(-1)); assertTrue(stats.isValidCustomBucket(0)); assertTrue(stats.isValidCustomBucket(1)); @@ -397,24 +397,24 @@ public class MeasuredEnergyStatsTest { assertFalse(stats.isValidCustomBucket(3)); assertFalse(stats.isValidCustomBucket(4)); - final MeasuredEnergyStats boringStats - = new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 0); + final MeasuredEnergyStats boringStats = + new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], 0); assertFalse(boringStats.isValidCustomBucket(-1)); assertFalse(boringStats.isValidCustomBucket(0)); assertFalse(boringStats.isValidCustomBucket(1)); } @Test - public void testGetAccumulatedCustomBucketEnergies() { - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 3); + public void testGetAccumulatedCustomBucketCharges() { + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], 3); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); stats.updateCustomBucket(2, 13); stats.updateCustomBucket(1, 70); - final long[] output = stats.getAccumulatedCustomBucketEnergies(); + final long[] output = stats.getAccumulatedCustomBucketCharges(); assertEquals(3, output.length); assertEquals(50, output[0]); @@ -423,73 +423,73 @@ public class MeasuredEnergyStatsTest { } @Test - public void testGetAccumulatedCustomBucketEnergies_empty() { - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 0); + public void testGetAccumulatedCustomBucketCharges_empty() { + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], 0); - final long[] output = stats.getAccumulatedCustomBucketEnergies(); + final long[] output = stats.getAccumulatedCustomBucketCharges(); assertEquals(0, output.length); } @Test - public void testGetNumberCustomEnergyBuckets() { - assertEquals(0, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 0) - .getNumberCustomEnergyBuckets()); - assertEquals(3, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 3) - .getNumberCustomEnergyBuckets()); + public void testGetNumberCustomChargeBuckets() { + assertEquals(0, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], 0) + .getNumberCustomPowerBuckets()); + assertEquals(3, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], 3) + .getNumberCustomPowerBuckets()); } @Test public void testReset() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final int numCustomBuckets = 2; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats stats - = new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5); - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40); + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats stats = + new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); MeasuredEnergyStats.resetIfNotNull(stats); - // All energy should be reset to 0 - for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) { + // All charges should be reset to 0 + for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { if (supportedStandardBuckets[i]) { assertTrue(stats.isStandardBucketSupported(i)); - assertEquals(0, stats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(0, stats.getAccumulatedStandardBucketCharge(i)); } else { assertFalse(stats.isStandardBucketSupported(i)); - assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketEnergy(i)); + assertEquals(POWER_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketCharge(i)); } } for (int i = 0; i < numCustomBuckets; i++) { - assertEquals(0, stats.getAccumulatedCustomBucketEnergy(i)); + assertEquals(0, stats.getAccumulatedCustomBucketCharge(i)); } // Values should increase as usual. - stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 70); - assertEquals(70L, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_ON)); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 70); + assertEquals(70L, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON)); stats.updateCustomBucket(1, 12); - assertEquals(12L, stats.getAccumulatedCustomBucketEnergy(1)); + assertEquals(12L, stats.getAccumulatedCustomBucketCharge(1)); } - /** Test that states are mapped to the expected energy buckets. Beware of mapping changes. */ + /** Test that states are mapped to the expected power buckets. Beware of mapping changes. */ @Test public void testStandardBucketMapping() { int exp; - exp = ENERGY_BUCKET_SCREEN_ON; - assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_ON)); - assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_VR)); - assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_ON_SUSPEND)); + exp = POWER_BUCKET_SCREEN_ON; + assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_ON)); + assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_VR)); + assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_ON_SUSPEND)); - exp = ENERGY_BUCKET_SCREEN_DOZE; - assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_DOZE)); - assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_DOZE_SUSPEND)); + exp = POWER_BUCKET_SCREEN_DOZE; + assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_DOZE)); + assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_DOZE_SUSPEND)); } } diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index fae89d65ddd1..c49fe8563dab 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -486,6 +486,8 @@ applications that come with the platform <permission name="android.permission.READ_PEOPLE_DATA" /> <!-- Permission required for CTS test - UiTranslationManagerTest --> <permission name="android.permission.MANAGE_UI_TRANSLATION" /> + <!-- Permission required for CTS test - ClipboardManagerTest --> + <permission name="android.permission.SET_CLIP_SOURCE" /> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/graphics/java/android/graphics/HardwareRendererObserver.java b/graphics/java/android/graphics/HardwareRendererObserver.java index da9d03c639f7..e2a05723166f 100644 --- a/graphics/java/android/graphics/HardwareRendererObserver.java +++ b/graphics/java/android/graphics/HardwareRendererObserver.java @@ -62,7 +62,7 @@ public class HardwareRendererObserver { * @param handler the Handler to use when invoking callbacks */ public HardwareRendererObserver(@NonNull OnFrameMetricsAvailableListener listener, - @NonNull long[] frameMetrics, @NonNull Handler handler) { + @NonNull long[] frameMetrics, @NonNull Handler handler, boolean waitForPresentTime) { if (handler == null || handler.getLooper() == null) { throw new NullPointerException("handler and its looper cannot be null"); } @@ -74,7 +74,7 @@ public class HardwareRendererObserver { mFrameMetrics = frameMetrics; mHandler = handler; mListener = listener; - mNativePtr = new VirtualRefBasePtr(nCreateObserver()); + mNativePtr = new VirtualRefBasePtr(nCreateObserver(waitForPresentTime)); } /*package*/ long getNativeInstance() { @@ -98,6 +98,6 @@ public class HardwareRendererObserver { }); } - private native long nCreateObserver(); + private native long nCreateObserver(boolean waitForPresentTime); private static native int nGetNextBuffer(long nativePtr, long[] data); } diff --git a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java index 992454285738..0006b92b1b9b 100644 --- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java +++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java @@ -18,6 +18,7 @@ package android.security.keystore2; import android.app.ActivityThread; import android.hardware.biometrics.BiometricManager; +import android.hardware.security.keymint.ErrorCode; import android.security.GateKeeper; import android.security.KeyStore; import android.security.KeyStoreException; @@ -183,15 +184,19 @@ abstract class KeyStoreCryptoOperationUtils { try { operation.abort(); } catch (KeyStoreException e) { - // We log this error, but we can afford to ignore it. Dropping the reference - // to the KeyStoreOperation is enough to clean up all related resources even - // in the Keystore daemon. We log it anyway, because it may indicate some - // underlying problem that is worth debugging. - Log.w( - "KeyStoreCryptoOperationUtils", - "Encountered error trying to abort a keystore operation.", - e - ); + // Invalid operation handle is very common at this point. It occurs every time + // an already finalized operation gets aborted. + if (e.getErrorCode() != ErrorCode.INVALID_OPERATION_HANDLE) { + // This error gets logged but ignored. Dropping the reference + // to the KeyStoreOperation is enough to clean up all related resources even + // in the Keystore daemon. It gets logged anyway, because it may indicate some + // underlying problem that is worth debugging. + Log.w( + "KeyStoreCryptoOperationUtils", + "Encountered error trying to abort a keystore operation.", + e + ); + } } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 9ddeb2fc6e1e..003649bf5b72 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -28,10 +28,13 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; +import android.app.TaskInfo; import android.content.Context; +import android.content.LocusId; import android.os.Binder; import android.os.IBinder; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.view.SurfaceControl; @@ -50,6 +53,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** * Unified task organizer for all components in the shell. @@ -96,6 +100,17 @@ public class ShellTaskOrganizer extends TaskOrganizer { } /** + * Callbacks for events on a task with a locus id. + */ + public interface LocusIdListener { + /** + * Notifies when a task with a locusId becomes visible, when a visible task's locusId + * changes, or if a previously visible task with a locusId becomes invisible. + */ + void onVisibilityChanged(int taskId, LocusId locus, boolean visible); + } + + /** * Keys map from either a task id or {@link TaskListenerType}. * @see #addListenerForTaskId * @see #addListenerForType @@ -109,6 +124,13 @@ public class ShellTaskOrganizer extends TaskOrganizer { /** @see #setPendingLaunchCookieListener */ private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>(); + // Keeps track of taskId's with visible locusIds. Used to notify any {@link LocusIdListener}s + // that might be set. + private final SparseArray<LocusId> mVisibleTasksWithLocusId = new SparseArray<>(); + + /** @see #addLocusIdListener */ + private final ArraySet<LocusIdListener> mLocusIdListeners = new ArraySet<>(); + private final Object mLock = new Object(); private StartingSurface mStartingSurface; @@ -257,6 +279,28 @@ public class ShellTaskOrganizer extends TaskOrganizer { } } + /** + * Adds a listener to be notified for {@link LocusId} visibility changes. + */ + public void addLocusIdListener(LocusIdListener listener) { + synchronized (mLock) { + mLocusIdListeners.add(listener); + for (int i = 0; i < mVisibleTasksWithLocusId.size(); i++) { + listener.onVisibilityChanged(mVisibleTasksWithLocusId.keyAt(i), + mVisibleTasksWithLocusId.valueAt(i), true /* visible */); + } + } + } + + /** + * Removes listener. + */ + public void removeLocusIdListener(LocusIdListener listener) { + synchronized (mLock) { + mLocusIdListeners.remove(listener); + } + } + @Override public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { if (mStartingSurface != null) { @@ -294,6 +338,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { if (listener != null) { listener.onTaskAppeared(info.getTaskInfo(), info.getLeash()); } + notifyLocusVisibilityIfNeeded(info.getTaskInfo()); notifySizeCompatUI(info.getTaskInfo(), listener); } @@ -310,6 +355,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { if (!updated && newListener != null) { newListener.onTaskInfoChanged(taskInfo); } + notifyLocusVisibilityIfNeeded(taskInfo); if (updated || !taskInfo.equalsForSizeCompat(data.getTaskInfo())) { // Notify the size compat UI if the listener or task info changed. notifySizeCompatUI(taskInfo, newListener); @@ -338,6 +384,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { if (listener != null) { listener.onTaskVanished(taskInfo); } + notifyLocusVisibilityIfNeeded(taskInfo); // Pass null for listener to remove the size compat UI on this task if there is any. notifySizeCompatUI(taskInfo, null /* taskListener */); } @@ -366,6 +413,39 @@ public class ShellTaskOrganizer extends TaskOrganizer { return true; } + private void notifyLocusVisibilityIfNeeded(TaskInfo taskInfo) { + final int taskId = taskInfo.taskId; + final LocusId prevLocus = mVisibleTasksWithLocusId.get(taskId); + final boolean sameLocus = Objects.equals(prevLocus, taskInfo.mTopActivityLocusId); + if (prevLocus == null) { + // New visible locus + if (taskInfo.mTopActivityLocusId != null && taskInfo.isVisible) { + mVisibleTasksWithLocusId.put(taskId, taskInfo.mTopActivityLocusId); + notifyLocusIdChange(taskId, taskInfo.mTopActivityLocusId, true /* visible */); + } + } else if (sameLocus && !taskInfo.isVisible) { + // Hidden locus + mVisibleTasksWithLocusId.remove(taskId); + notifyLocusIdChange(taskId, taskInfo.mTopActivityLocusId, false /* visible */); + } else if (!sameLocus) { + // Changed locus + if (taskInfo.isVisible) { + mVisibleTasksWithLocusId.put(taskId, taskInfo.mTopActivityLocusId); + notifyLocusIdChange(taskId, prevLocus, false /* visible */); + notifyLocusIdChange(taskId, taskInfo.mTopActivityLocusId, true /* visible */); + } else { + mVisibleTasksWithLocusId.remove(taskInfo.taskId); + notifyLocusIdChange(taskId, prevLocus, false /* visible */); + } + } + } + + private void notifyLocusIdChange(int taskId, LocusId locus, boolean visible) { + for (int i = 0; i < mLocusIdListeners.size(); i++) { + mLocusIdListeners.valueAt(i).onVisibilityChanged(taskId, locus, visible); + } + } + /** * Notifies {@link SizeCompatUIController} about the size compat info changed on the give Task * to update the UI accordingly. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 8697be9db3fd..d6079b6ce984 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -28,6 +28,7 @@ import android.app.PendingIntent; import android.app.Person; import android.content.Context; import android.content.Intent; +import android.content.LocusId; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; @@ -62,13 +63,16 @@ public class Bubble implements BubbleViewProvider { private final String mKey; @Nullable private final String mGroupKey; + @Nullable + private final LocusId mLocusId; + private final Executor mMainExecutor; private long mLastUpdated; private long mLastAccessed; @Nullable - private Bubbles.NotificationSuppressionChangedListener mSuppressionListener; + private Bubbles.SuppressionChangedListener mSuppressionListener; /** Whether the bubble should show a dot for the notification indicating updated content. */ private boolean mShowBubbleUpdateDot = true; @@ -163,13 +167,14 @@ public class Bubble implements BubbleViewProvider { */ Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo, final int desiredHeight, final int desiredHeightResId, @Nullable final String title, - int taskId, Executor mainExecutor) { + int taskId, @Nullable final String locus, Executor mainExecutor) { Objects.requireNonNull(key); Objects.requireNonNull(shortcutInfo); mMetadataShortcutId = shortcutInfo.getId(); mShortcutInfo = shortcutInfo; mKey = key; mGroupKey = null; + mLocusId = locus != null ? new LocusId(locus) : null; mFlags = 0; mUser = shortcutInfo.getUserHandle(); mPackageName = shortcutInfo.getPackage(); @@ -184,11 +189,12 @@ public class Bubble implements BubbleViewProvider { @VisibleForTesting(visibility = PRIVATE) Bubble(@NonNull final BubbleEntry entry, - @Nullable final Bubbles.NotificationSuppressionChangedListener listener, + @Nullable final Bubbles.SuppressionChangedListener listener, final Bubbles.PendingIntentCanceledListener intentCancelListener, Executor mainExecutor) { mKey = entry.getKey(); mGroupKey = entry.getGroupKey(); + mLocusId = entry.getLocusId(); mSuppressionListener = listener; mIntentCancelListener = intent -> { if (mIntent != null) { @@ -216,6 +222,10 @@ public class Bubble implements BubbleViewProvider { return mGroupKey; } + public LocusId getLocusId() { + return mLocusId; + } + public UserHandle getUser() { return mUser; } @@ -550,6 +560,21 @@ public class Bubble implements BubbleViewProvider { } /** + * Whether this bubble is currently being hidden from the stack. + */ + boolean isSuppressed() { + return (mFlags & Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE) != 0; + } + + /** + * Whether this bubble is able to be suppressed (i.e. has the developer opted into the API to + * hide the bubble when in the same content). + */ + boolean isSuppressable() { + return (mFlags & Notification.BubbleMetadata.FLAG_SHOULD_SUPPRESS_BUBBLE) != 0; + } + + /** * Whether this notification conversation is important. */ boolean isImportantConversation() { @@ -574,6 +599,26 @@ public class Bubble implements BubbleViewProvider { } /** + * Sets whether this bubble should be suppressed from the stack. + */ + public void setSuppressBubble(boolean suppressBubble) { + if (!isSuppressable()) { + Log.e(TAG, "calling setSuppressBubble on " + + getKey() + " when bubble not suppressable"); + return; + } + boolean prevSuppressed = isSuppressed(); + if (suppressBubble) { + mFlags |= Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE; + } else { + mFlags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE; + } + if (prevSuppressed != suppressBubble && mSuppressionListener != null) { + mSuppressionListener.onBubbleNotificationSuppressionChange(this); + } + } + + /** * Sets whether the bubble for this notification should show a dot indicating updated content. */ void setShowDot(boolean showDot) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index d31e637b778e..620c382ef183 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -16,7 +16,6 @@ package com.android.wm.shell.bubbles; -import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; @@ -28,7 +27,6 @@ import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_BOT import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_LEFT; import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_NONE; import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_RIGHT; -import static com.android.wm.shell.bubbles.Bubbles.DISMISS_AGED; import static com.android.wm.shell.bubbles.Bubbles.DISMISS_BLOCKED; import static com.android.wm.shell.bubbles.Bubbles.DISMISS_GROUP_CANCELLED; import static com.android.wm.shell.bubbles.Bubbles.DISMISS_INVALID_INTENT; @@ -42,7 +40,6 @@ import static com.android.wm.shell.bubbles.Bubbles.DISMISS_USER_CHANGED; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.ActivityManager; -import android.app.ActivityTaskManager; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; @@ -243,15 +240,15 @@ public class BubbleController { mBubbleData = data; mBubbleData.setListener(mBubbleDataListener); mBubbleData.setSuppressionChangedListener(bubble -> { - // Make sure NoMan knows it's not showing in the shade anymore so anyone querying it - // can tell. + // Make sure NoMan knows suppression state so that anyone querying it can tell. try { mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(), - !bubble.showInShade()); + !bubble.showInShade(), bubble.isSuppressed()); } catch (RemoteException e) { // Bad things have happened } }); + mBubbleData.setPendingIntentCancelledListener(bubble -> { if (bubble.getBubbleIntent() == null) { return; @@ -282,6 +279,8 @@ public class BubbleController { mBubbleIconFactory = new BubbleIconFactory(context); mTaskOrganizer = organizer; + mTaskOrganizer.addLocusIdListener((taskId, locus, visible) -> + mBubbleData.onLocusVisibilityChanged(taskId, locus, visible)); launcherApps.registerCallback(new LauncherApps.Callback() { @Override @@ -1044,6 +1043,14 @@ public class BubbleController { } } + if (update.suppressedBubble != null && mStackView != null) { + mStackView.setBubbleVisibility(update.suppressedBubble, false); + } + + if (update.unsuppressedBubble != null && mStackView != null) { + mStackView.setBubbleVisibility(update.unsuppressedBubble, true); + } + // Expanding? Apply this last. if (update.expandedChanged && update.expanded) { if (mStackView != null) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index 53b75373a647..f6e6b8f3b700 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -24,7 +24,10 @@ import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME import android.annotation.NonNull; import android.app.PendingIntent; import android.content.Context; +import android.content.LocusId; import android.content.pm.ShortcutInfo; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.Pair; import android.view.View; @@ -75,6 +78,8 @@ public class BubbleData { @Nullable Bubble updatedBubble; @Nullable Bubble addedOverflowBubble; @Nullable Bubble removedOverflowBubble; + @Nullable Bubble suppressedBubble; + @Nullable Bubble unsuppressedBubble; // Pair with Bubble and @DismissReason Integer final List<Pair<Bubble, Integer>> removedBubbles = new ArrayList<>(); @@ -95,7 +100,9 @@ public class BubbleData { || !removedBubbles.isEmpty() || addedOverflowBubble != null || removedOverflowBubble != null - || orderChanged; + || orderChanged + || suppressedBubble != null + || unsuppressedBubble != null; } void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) { @@ -125,6 +132,11 @@ public class BubbleData { private final List<Bubble> mOverflowBubbles; /** Bubbles that are being loaded but haven't been added to the stack just yet. */ private final HashMap<String, Bubble> mPendingBubbles; + /** Bubbles that are suppressed due to locusId. */ + private final ArrayMap<LocusId, Bubble> mSuppressedBubbles = new ArrayMap<>(); + /** Visible locusIds. */ + private final ArraySet<LocusId> mVisibleLocusIds = new ArraySet<>(); + private BubbleViewProvider mSelectedBubble; private final BubbleOverflow mOverflow; private boolean mShowingOverflow; @@ -141,7 +153,7 @@ public class BubbleData { private Listener mListener; @Nullable - private Bubbles.NotificationSuppressionChangedListener mSuppressionListener; + private Bubbles.SuppressionChangedListener mSuppressionListener; private Bubbles.PendingIntentCanceledListener mCancelledListener; /** @@ -173,7 +185,7 @@ public class BubbleData { } public void setSuppressionChangedListener( - Bubbles.NotificationSuppressionChangedListener listener) { + Bubbles.SuppressionChangedListener listener) { mSuppressionListener = listener; } @@ -321,6 +333,18 @@ public class BubbleData { bubble.setSuppressNotification(suppress); bubble.setShowDot(!isBubbleExpandedAndSelected /* show */); + LocusId locusId = bubble.getLocusId(); + if (locusId != null) { + boolean isSuppressed = mSuppressedBubbles.containsKey(locusId); + if (isSuppressed && (!bubble.isSuppressed() || !bubble.isSuppressable())) { + mSuppressedBubbles.remove(locusId); + mStateChange.unsuppressedBubble = bubble; + } else if (!isSuppressed && (bubble.isSuppressed() + || bubble.isSuppressable() && mVisibleLocusIds.contains(locusId))) { + mSuppressedBubbles.put(locusId, bubble); + mStateChange.suppressedBubble = bubble; + } + } dispatchPendingChanges(); } @@ -581,6 +605,43 @@ public class BubbleData { dispatchPendingChanges(); } + /** + * Called in response to the visibility of a locusId changing. A locusId is set on a task + * and if there's a matching bubble for that locusId then the bubble may be hidden or shown + * depending on the visibility of the locusId. + * + * @param taskId the taskId associated with the locusId visibility change. + * @param locusId the locusId whose visibility has changed. + * @param visible whether the task with the locusId is visible or not. + */ + public void onLocusVisibilityChanged(int taskId, LocusId locusId, boolean visible) { + Bubble matchingBubble = getBubbleInStackWithLocusId(locusId); + // Don't add the locus if it's from a bubble'd activity, we only suppress for non-bubbled. + if (visible && (matchingBubble == null || matchingBubble.getTaskId() != taskId)) { + mVisibleLocusIds.add(locusId); + } else { + mVisibleLocusIds.remove(locusId); + } + if (matchingBubble == null) { + return; + } + boolean isAlreadySuppressed = mSuppressedBubbles.get(locusId) != null; + if (visible && !isAlreadySuppressed && matchingBubble.isSuppressable() + && taskId != matchingBubble.getTaskId()) { + mSuppressedBubbles.put(locusId, matchingBubble); + matchingBubble.setSuppressBubble(true); + mStateChange.suppressedBubble = matchingBubble; + dispatchPendingChanges(); + } else if (!visible) { + Bubble unsuppressedBubble = mSuppressedBubbles.remove(locusId); + if (unsuppressedBubble != null) { + unsuppressedBubble.setSuppressBubble(false); + mStateChange.unsuppressedBubble = unsuppressedBubble; + } + dispatchPendingChanges(); + } + } + private void dispatchPendingChanges() { if (mListener != null && mStateChange.anythingChanged()) { mListener.applyUpdate(mStateChange); @@ -792,6 +853,18 @@ public class BubbleData { } @Nullable + private Bubble getBubbleInStackWithLocusId(LocusId locusId) { + if (locusId == null) return null; + for (int i = 0; i < mBubbles.size(); i++) { + Bubble bubble = mBubbles.get(i); + if (locusId.equals(bubble.getLocusId())) { + return bubble; + } + } + return null; + } + + @Nullable Bubble getBubbleWithView(View view) { for (int i = 0; i < mBubbles.size(); i++) { Bubble bubble = mBubbles.get(i); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt index 241755227af0..bfacd1cfe90e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt @@ -81,7 +81,8 @@ internal class BubbleDataRepository( b.rawDesiredHeight, b.rawDesiredHeightResId, b.title, - b.taskId + b.taskId, + b.locusId?.id ) } } @@ -172,6 +173,7 @@ internal class BubbleDataRepository( entity.desiredHeightResId, entity.title, entity.taskId, + entity.locus, mainExecutor ) } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java index ff68861eb40c..5f428269fb06 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java @@ -21,6 +21,7 @@ import static android.app.Notification.FLAG_BUBBLE; import android.app.Notification; import android.app.Notification.BubbleMetadata; import android.app.NotificationManager.Policy; +import android.content.LocusId; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.StatusBarNotification; @@ -75,6 +76,11 @@ public class BubbleEntry { return mSbn.getGroupKey(); } + /** @return the {@link LocusId} for this notification, if it exists. */ + public LocusId getLocusId() { + return mSbn.getNotification().getLocusId(); + } + /** @return the {@link BubbleMetadata} in the {@link StatusBarNotification}. */ @Nullable public BubbleMetadata getBubbleMetadata() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java index 39e4e1a09019..8ee2b40d5985 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java @@ -20,29 +20,22 @@ import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_OVERFLOW; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; -import android.app.Activity; import android.content.Context; -import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; -import android.os.Bundle; -import android.os.IBinder; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.view.accessibility.AccessibilityNodeInfo; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 78820a8fa870..64a44ca9e7e9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -912,9 +912,6 @@ public class BubbleStackView extends FrameLayout removeOnLayoutChangeListener(mOrientationChangedListener); }; - // This must be a separate OnDrawListener since it should be called for every draw. - getViewTreeObserver().addOnDrawListener(mSystemGestureExcludeUpdater); - final ColorMatrix animatedMatrix = new ColorMatrix(); final ColorMatrix darkenMatrix = new ColorMatrix(); @@ -1274,12 +1271,14 @@ public class BubbleStackView extends FrameLayout protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnComputeInternalInsetsListener(this); + getViewTreeObserver().addOnDrawListener(mSystemGestureExcludeUpdater); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeOnPreDrawListener(mViewUpdater); + getViewTreeObserver().removeOnDrawListener(mSystemGestureExcludeUpdater); getViewTreeObserver().removeOnComputeInternalInsetsListener(this); if (mBubbleOverflow != null) { mBubbleOverflow.cleanUpExpandedState(); @@ -1688,6 +1687,13 @@ public class BubbleStackView extends FrameLayout notifyExpansionChanged(mExpandedBubble, mIsExpanded); } + void setBubbleVisibility(Bubble b, boolean visible) { + if (b.getIconView() != null) { + b.getIconView().setVisibility(visible ? VISIBLE : GONE); + } + // TODO(b/181166384): Animate in / out & handle adjusting how the bubbles overlap + } + /** * Asks the BubbleController to hide the IME from anywhere, whether it's focused on Bubbles or * not. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index 8e061e9c9874..98978b562011 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -234,8 +234,8 @@ public interface Bubbles { void onBubbleExpandChanged(boolean isExpanding, String key); } - /** Listener to be notified when a bubbles' notification suppression state changes.*/ - interface NotificationSuppressionChangedListener { + /** Listener to be notified when the flags for notification or bubble suppression changes.*/ + interface SuppressionChangedListener { /** Called when the notification suppression state of a bubble changes. */ void onBubbleNotificationSuppressionChange(Bubble bubble); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt index d5cab5af42e4..186b9b1efa9a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt @@ -26,5 +26,6 @@ data class BubbleEntity( val desiredHeight: Int, @DimenRes val desiredHeightResId: Int, val title: String? = null, - val taskId: Int + val taskId: Int, + val locus: String? = null ) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt index 470011b136fe..a74445bba1ab 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt @@ -40,6 +40,7 @@ private const val ATTR_DESIRED_HEIGHT = "h" private const val ATTR_DESIRED_HEIGHT_RES_ID = "hid" private const val ATTR_TITLE = "t" private const val ATTR_TASK_ID = "tid" +private const val ATTR_LOCUS = "l" /** * Writes the bubbles in xml format into given output stream. @@ -73,6 +74,7 @@ private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) { serializer.attribute(null, ATTR_DESIRED_HEIGHT_RES_ID, bubble.desiredHeightResId.toString()) bubble.title?.let { serializer.attribute(null, ATTR_TITLE, it) } serializer.attribute(null, ATTR_TASK_ID, bubble.taskId.toString()) + bubble.locus?.let { serializer.attribute(null, ATTR_LOCUS, it) } serializer.endTag(null, TAG_BUBBLE) } catch (e: IOException) { throw RuntimeException(e) @@ -107,7 +109,8 @@ private fun readXmlEntry(parser: XmlPullParser): BubbleEntity? { parser.getAttributeWithName(ATTR_DESIRED_HEIGHT)?.toInt() ?: return null, parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null, parser.getAttributeWithName(ATTR_TITLE), - parser.getAttributeWithName(ATTR_TASK_ID)?.toInt() ?: INVALID_TASK_ID + parser.getAttributeWithName(ATTR_TASK_ID)?.toInt() ?: INVALID_TASK_ID, + parser.getAttributeWithName(ATTR_LOCUS) ) } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 7ed7fd0096bd..9ec7c0d173dd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -58,13 +58,13 @@ import android.view.SurfaceControl; import android.window.TaskOrganizer; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; -import android.window.WindowContainerTransactionCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.pip.phone.PipMotionHelper; @@ -123,6 +123,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } } + private final SyncTransactionQueue mSyncTransactionQueue; private final PipBoundsState mPipBoundsState; private final PipBoundsAlgorithm mPipBoundsAlgorithm; private final @NonNull PipMenuController mPipMenuController; @@ -205,7 +206,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, */ private boolean mInSwipePipToHomeTransition; - public PipTaskOrganizer(Context context, @NonNull PipBoundsState pipBoundsState, + public PipTaskOrganizer(Context context, + @NonNull SyncTransactionQueue syncTransactionQueue, + @NonNull PipBoundsState pipBoundsState, @NonNull PipBoundsAlgorithm boundsHandler, @NonNull PipMenuController pipMenuController, @NonNull PipAnimationController pipAnimationController, @@ -216,6 +219,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, @NonNull PipUiEventLogger pipUiEventLogger, @NonNull ShellTaskOrganizer shellTaskOrganizer, @ShellMainThread ShellExecutor mainExecutor) { + mSyncTransactionQueue = syncTransactionQueue; mPipBoundsState = pipBoundsState; mPipBoundsAlgorithm = boundsHandler; mPipMenuController = pipMenuController; @@ -337,21 +341,16 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, : WINDOWING_MODE_FULLSCREEN); wct.setBounds(mToken, destinationBounds); wct.setBoundsChangeTransaction(mToken, tx); - mTaskOrganizer.applySyncTransaction(wct, new WindowContainerTransactionCallback() { - @Override - public void onTransactionReady(int id, SurfaceControl.Transaction t) { - mMainExecutor.execute(() -> { - t.apply(); - // Make sure to grab the latest source hint rect as it could have been - // updated right after applying the windowing mode change. - final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( - mPictureInPictureParams, destinationBounds); - scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds, - 0 /* startingAngle */, sourceHintRect, direction, - animationDurationMs, null /* updateBoundsCallback */); - mState = State.EXITING_PIP; - }); - } + mSyncTransactionQueue.queue(wct); + mSyncTransactionQueue.runInSync(t -> { + // Make sure to grab the latest source hint rect as it could have been + // updated right after applying the windowing mode change. + final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( + mPictureInPictureParams, destinationBounds); + scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds, + 0 /* startingAngle */, sourceHintRect, direction, + animationDurationMs, null /* updateBoundsCallback */); + mState = State.EXITING_PIP; }); } @@ -502,18 +501,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); wct.setBounds(mToken, destinationBounds); wct.scheduleFinishEnterPip(mToken, destinationBounds); - // TODO: Migrate to SyncTransactionQueue - mTaskOrganizer.applySyncTransaction(wct, new WindowContainerTransactionCallback() { - @Override - public void onTransactionReady(int id, SurfaceControl.Transaction t) { - mMainExecutor.execute(() -> { - t.apply(); - if (runnable != null) { - runnable.run(); - } - }); - } - }); + mSyncTransactionQueue.queue(wct); + if (runnable != null) { + mSyncTransactionQueue.runInSync(t -> runnable.run()); + } } private void sendOnPipTransitionStarted( @@ -951,40 +942,37 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final SurfaceControl snapshotSurface = mTaskOrganizer.takeScreenshot(mToken); mSurfaceTransactionHelper.reparentAndShowSurfaceSnapshot( mSurfaceControlTransactionFactory.getTransaction(), mLeash, snapshotSurface); - mTaskOrganizer.applySyncTransaction(wct, new WindowContainerTransactionCallback() { - @Override - public void onTransactionReady(int id, @NonNull SurfaceControl.Transaction t) { - // Scale the snapshot from its pre-resize bounds to the post-resize bounds. - final Rect snapshotSrc = new Rect(0, 0, snapshotSurface.getWidth(), - snapshotSurface.getHeight()); - final Rect snapshotDest = new Rect(0, 0, destinationBounds.width(), - destinationBounds.height()); - mSurfaceTransactionHelper.scale(t, snapshotSurface, snapshotSrc, snapshotDest); - t.apply(); - - mMainExecutor.execute(() -> { - // Start animation to fade out the snapshot. - final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f); - animator.setDuration(mEnterExitAnimationDuration); - animator.addUpdateListener(animation -> { - final float alpha = (float) animation.getAnimatedValue(); + mSyncTransactionQueue.queue(wct); + mSyncTransactionQueue.runInSync(t -> { + // Scale the snapshot from its pre-resize bounds to the post-resize bounds. + final Rect snapshotSrc = new Rect(0, 0, snapshotSurface.getWidth(), + snapshotSurface.getHeight()); + final Rect snapshotDest = new Rect(0, 0, destinationBounds.width(), + destinationBounds.height()); + mSurfaceTransactionHelper.scale(t, snapshotSurface, snapshotSrc, snapshotDest); + + mMainExecutor.execute(() -> { + // Start animation to fade out the snapshot. + final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f); + animator.setDuration(mEnterExitAnimationDuration); + animator.addUpdateListener(animation -> { + final float alpha = (float) animation.getAnimatedValue(); + final SurfaceControl.Transaction transaction = + mSurfaceControlTransactionFactory.getTransaction(); + transaction.setAlpha(snapshotSurface, alpha); + transaction.apply(); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); - tx.setAlpha(snapshotSurface, alpha); + tx.remove(snapshotSurface); tx.apply(); - }); - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - final SurfaceControl.Transaction tx = - mSurfaceControlTransactionFactory.getTransaction(); - tx.remove(snapshotSurface); - tx.apply(); - } - }); - animator.start(); + } }); - } + animator.start(); + }); }); } else { applyFinishBoundsResize(wct, direction); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index 06b492dcb409..df0a856db73c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -27,6 +27,7 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCR import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -37,10 +38,12 @@ import static org.mockito.Mockito.verify; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; +import android.content.LocusId; import android.content.pm.ParceledListSlice; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.util.SparseArray; import android.view.SurfaceControl; import android.window.ITaskOrganizer; import android.window.ITaskOrganizerController; @@ -105,6 +108,20 @@ public class ShellTaskOrganizerTests { } } + private class TrackingLocusIdListener implements ShellTaskOrganizer.LocusIdListener { + final SparseArray<LocusId> visibleLocusTasks = new SparseArray<>(); + final SparseArray<LocusId> invisibleLocusTasks = new SparseArray<>(); + @Override + public void onVisibilityChanged(int taskId, LocusId locus, boolean visible) { + if (visible) { + visibleLocusTasks.put(taskId, locus); + } else { + invisibleLocusTasks.put(taskId, locus); + } + } + } + + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -299,6 +316,123 @@ public class ShellTaskOrganizerTests { null /* taskConfig */, null /* sizeCompatActivity*/, null /* taskListener */); } + @Test + public void testAddLocusListener() { + RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW); + task1.isVisible = true; + task1.mTopActivityLocusId = new LocusId("10"); + + RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_FULLSCREEN); + task2.isVisible = true; + task2.mTopActivityLocusId = new LocusId("20"); + + RunningTaskInfo task3 = createTaskInfo(3, WINDOWING_MODE_FULLSCREEN); + task3.isVisible = true; + + mOrganizer.onTaskAppeared(task1, null); + mOrganizer.onTaskAppeared(task2, null); + mOrganizer.onTaskAppeared(task3, null); + + TrackingLocusIdListener listener = new TrackingLocusIdListener(); + mOrganizer.addLocusIdListener(listener); + + // Listener should have the locus tasks even if added after the tasks appear + assertEquals(listener.visibleLocusTasks.get(task1.taskId), task1.mTopActivityLocusId); + assertEquals(listener.visibleLocusTasks.get(task2.taskId), task2.mTopActivityLocusId); + assertFalse(listener.visibleLocusTasks.contains(task3.taskId)); + } + + @Test + public void testLocusListener_appearVanish() { + TrackingLocusIdListener listener = new TrackingLocusIdListener(); + mOrganizer.addLocusIdListener(listener); + + RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN); + task1.mTopActivityLocusId = new LocusId("10"); + + task1.isVisible = true; + mOrganizer.onTaskAppeared(task1, null); + assertTrue(listener.visibleLocusTasks.contains(task1.taskId)); + assertEquals(listener.visibleLocusTasks.get(task1.taskId), task1.mTopActivityLocusId); + + task1.isVisible = false; + mOrganizer.onTaskVanished(task1); + assertTrue(listener.invisibleLocusTasks.contains(task1.taskId)); + assertEquals(listener.invisibleLocusTasks.get(task1.taskId), task1.mTopActivityLocusId); + } + + @Test + public void testLocusListener_infoChanged() { + TrackingLocusIdListener listener = new TrackingLocusIdListener(); + mOrganizer.addLocusIdListener(listener); + + RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW); + task1.isVisible = true; + mOrganizer.onTaskAppeared(task1, null); + assertEquals(listener.visibleLocusTasks.size(), 0); + + task1.mTopActivityLocusId = new LocusId("10"); + mOrganizer.onTaskInfoChanged(task1); + assertTrue(listener.visibleLocusTasks.contains(task1.taskId)); + assertEquals(listener.visibleLocusTasks.get(task1.taskId), task1.mTopActivityLocusId); + + LocusId prevLocus = task1.mTopActivityLocusId; + task1.mTopActivityLocusId = new LocusId("20"); + mOrganizer.onTaskInfoChanged(task1); + + // New locus is in visible list + assertTrue(listener.visibleLocusTasks.contains(task1.taskId)); + assertEquals(listener.visibleLocusTasks.get(task1.taskId), task1.mTopActivityLocusId); + // Old locus in invisible list + assertTrue(listener.invisibleLocusTasks.contains(task1.taskId)); + assertEquals(listener.invisibleLocusTasks.get(task1.taskId), prevLocus); + } + + @Test + public void testLocusListener_infoChanged_notVisible() { + TrackingLocusIdListener listener = new TrackingLocusIdListener(); + mOrganizer.addLocusIdListener(listener); + + RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN); + task1.isVisible = true; + mOrganizer.onTaskAppeared(task1, null); + + task1.mTopActivityLocusId = new LocusId("10"); + mOrganizer.onTaskInfoChanged(task1); + assertTrue(listener.visibleLocusTasks.contains(task1.taskId)); + assertEquals(listener.visibleLocusTasks.get(task1.taskId), task1.mTopActivityLocusId); + + LocusId prevLocus = task1.mTopActivityLocusId; + task1.mTopActivityLocusId = new LocusId("20"); + task1.isVisible = false; + mOrganizer.onTaskInfoChanged(task1); + + // New locus for previously reported task in invisible list (since the task wasn't visible). + assertTrue(listener.invisibleLocusTasks.contains(task1.taskId)); + assertEquals(listener.invisibleLocusTasks.get(task1.taskId), prevLocus); + } + + @Test + public void testLocusListener_noLocusNotNotified() { + TrackingLocusIdListener listener = new TrackingLocusIdListener(); + mOrganizer.addLocusIdListener(listener); + + RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW); + task1.isVisible = true; + mOrganizer.onTaskAppeared(task1, null); + assertEquals(listener.visibleLocusTasks.size(), 0); + assertEquals(listener.invisibleLocusTasks.size(), 0); + + mOrganizer.onTaskInfoChanged(task1); + assertEquals(listener.visibleLocusTasks.size(), 0); + assertEquals(listener.invisibleLocusTasks.size(), 0); + + task1.isVisible = false; + mOrganizer.onTaskVanished(task1); + assertEquals(listener.visibleLocusTasks.size(), 0); + assertEquals(listener.invisibleLocusTasks.size(), 0); + } + private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) { RunningTaskInfo taskInfo = new RunningTaskInfo(); taskInfo.taskId = taskId; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java index d3a736e9153e..9a80a5545984 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java @@ -106,7 +106,7 @@ public class BubbleDataTest extends ShellTestCase { private ArgumentCaptor<BubbleData.Update> mUpdateCaptor; @Mock - private Bubbles.NotificationSuppressionChangedListener mSuppressionListener; + private Bubbles.SuppressionChangedListener mSuppressionListener; @Mock private Bubbles.PendingIntentCanceledListener mPendingIntentCanceledListener; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java index fc828b30279f..819a984b4a77 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java @@ -63,7 +63,7 @@ public class BubbleTest extends ShellTestCase { private Bubble mBubble; @Mock - private Bubbles.NotificationSuppressionChangedListener mSuppressionListener; + private Bubbles.SuppressionChangedListener mSuppressionListener; @Before public void setUp() { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt index bdf75fcd8816..2f064ac95204 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt @@ -32,10 +32,12 @@ import org.junit.runner.RunWith class BubblePersistentRepositoryTest : ShellTestCase() { private val bubbles = listOf( - BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0, null, 1), - BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title", 2), + // user, package, shortcut, notification key, height, res-height, title, taskId, locusId + BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0, null, 1, null), + BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title", + 2, null), BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0, null, - INVALID_TASK_ID) + INVALID_TASK_ID, "key-3") ) private lateinit var repository: BubblePersistentRepository diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt index 05795fde7d6c..03aa6c2eba12 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleVolatileRepositoryTest.kt @@ -38,12 +38,13 @@ class BubbleVolatileRepositoryTest : ShellTestCase() { private val user0 = UserHandle.of(0) private val user10 = UserHandle.of(10) + // user, package, shortcut, notification key, height, res-height, title, taskId, locusId private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0, - null, 1) + null, 1, null) private val bubble2 = BubbleEntity(10, "com.example.chat", "alice and bob", - "key-2", 0, 16537428, "title", 2) + "key-2", 0, 16537428, "title", 2, null) private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0, - null, INVALID_TASK_ID) + null, INVALID_TASK_ID, "key-3") private val bubbles = listOf(bubble1, bubble2, bubble3) @@ -108,13 +109,14 @@ class BubbleVolatileRepositoryTest : ShellTestCase() { @Test fun testAddBubbleMatchesByKey() { - val bubble = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, "title", 1) + val bubble = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, "title", + 1, null) repository.addBubbles(listOf(bubble)) assertEquals(bubble, repository.bubbles.get(0)) // Same key as first bubble but different entry val bubbleModified = BubbleEntity(0, "com.example.pkg", "shortcut-id", "key", 120, 0, - "different title", 2) + "different title", 2, null) repository.addBubbles(listOf(bubbleModified)) assertEquals(bubbleModified, repository.bubbles.get(0)) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt index 839b873d0c23..8d719e7a7378 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt @@ -32,10 +32,12 @@ import java.io.ByteArrayOutputStream class BubbleXmlHelperTest : ShellTestCase() { private val bubbles = listOf( + // user, package, shortcut, notification key, height, res-height, title, taskId, locusId BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0, null, 1), - BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title", 2), + BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title", + 2, null), BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0, null, - INVALID_TASK_ID) + INVALID_TASK_ID, "l3") ) @Test @@ -43,7 +45,7 @@ class BubbleXmlHelperTest : ShellTestCase() { val expectedEntries = """ <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" tid="1" /> <bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" tid="2" /> -<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" tid="-1" /> +<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" tid="-1" l="l3" /> """.trimIndent() ByteArrayOutputStream().use { writeXml(it, bubbles) @@ -60,7 +62,7 @@ class BubbleXmlHelperTest : ShellTestCase() { <bs v="1"> <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" tid="1" /> <bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" tid="2" /> -<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" tid="-1" /> +<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" tid="-1" l="l3" /> </bs> """.trimIndent() val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8))) @@ -97,7 +99,32 @@ class BubbleXmlHelperTest : ShellTestCase() { BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0, null, INVALID_TASK_ID) ) + val src = """ +<?xml version='1.0' encoding='utf-8' standalone='yes' ?> +<bs v="1"> +<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" /> +<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" /> +<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" /> +</bs> + """.trimIndent() + val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8))) + assertEquals("failed parsing bubbles from xml\n$src", expectedBubbles, actual) + } + /** + * LocusId is optional so it can be added without a version change, this test makes sure that + * works. + */ + @Test + fun testXMLWithoutLocusToLocus() { + val expectedBubbles = listOf( + BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0, null, + INVALID_TASK_ID, null), + BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title", + INVALID_TASK_ID, null), + BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0, null, + INVALID_TASK_ID, null) + ) val src = """ <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <bs v="1"> diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index 195b701a1c26..d687e8d76d91 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -45,6 +45,7 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.pip.phone.PhonePipMenuController; @@ -65,8 +66,8 @@ import java.util.Optional; public class PipTaskOrganizerTest extends ShellTestCase { private PipTaskOrganizer mSpiedPipTaskOrganizer; - @Mock private DisplayController mMockdDisplayController; - + @Mock private DisplayController mMockDisplayController; + @Mock private SyncTransactionQueue mMockSyncTransactionQueue; @Mock private PhonePipMenuController mMockPhonePipMenuController; @Mock private PipAnimationController mMockPipAnimationController; @Mock private PipTransitionController mMockPipTransitionController; @@ -89,10 +90,11 @@ public class PipTaskOrganizerTest extends ShellTestCase { mPipBoundsState = new PipBoundsState(mContext); mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState); mMainExecutor = new TestShellExecutor(); - mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext, mPipBoundsState, + mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext, + mMockSyncTransactionQueue, mPipBoundsState, mPipBoundsAlgorithm, mMockPhonePipMenuController, mMockPipAnimationController, mMockPipSurfaceTransactionHelper, - mMockPipTransitionController, mMockOptionalSplitScreen, mMockdDisplayController, + mMockPipTransitionController, mMockOptionalSplitScreen, mMockDisplayController, mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor)); mMainExecutor.flushAll(); preparePipTaskOrg(); @@ -105,7 +107,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void instantiatePipTaskOrganizer_addsDisplayWindowListener() { - verify(mMockdDisplayController).addDisplayWindowListener(any()); + verify(mMockDisplayController).addDisplayWindowListener(any()); } @Test diff --git a/libs/hwui/FrameMetricsObserver.h b/libs/hwui/FrameMetricsObserver.h index b93f07853242..ef1f5aabcbd8 100644 --- a/libs/hwui/FrameMetricsObserver.h +++ b/libs/hwui/FrameMetricsObserver.h @@ -24,6 +24,24 @@ namespace uirenderer { class FrameMetricsObserver : public VirtualLightRefBase { public: virtual void notify(const int64_t* buffer) = 0; + bool waitForPresentTime() const { return mWaitForPresentTime; }; + + /** + * Create a new metrics observer. An observer that watches present time gets notified at a + * different time than the observer that doesn't. + * + * The observer that doesn't want present time is notified about metrics just after the frame + * is completed. This is the default behaviour that's used by public API's. + * + * An observer that watches present time is notified about metrics after the actual display + * present time is known. + * WARNING! This observer may not receive metrics for the last several frames that the app + * produces. + */ + FrameMetricsObserver(bool waitForPresentTime) : mWaitForPresentTime(waitForPresentTime) {} + +private: + const bool mWaitForPresentTime; }; } // namespace uirenderer diff --git a/libs/hwui/FrameMetricsReporter.h b/libs/hwui/FrameMetricsReporter.h index 0643e790d00b..3f2dc1244085 100644 --- a/libs/hwui/FrameMetricsReporter.h +++ b/libs/hwui/FrameMetricsReporter.h @@ -55,13 +55,24 @@ public: return mObservers.size() > 0; } - void reportFrameMetrics(const int64_t* stats) { + /** + * Notify observers about the metrics contained in 'stats'. + * If an observer is waiting for present time, notify when 'stats' has present time. + * + * If an observer does not want present time, only notify when 'hasPresentTime' is false. + * Never notify both types of observers from the same callback, because the callback with + * 'hasPresentTime' is sent at a different time than the one without. + */ + void reportFrameMetrics(const int64_t* stats, bool hasPresentTime) { FatVector<sp<FrameMetricsObserver>, 10> copy; { std::lock_guard lock(mObserversLock); copy.reserve(mObservers.size()); for (size_t i = 0; i < mObservers.size(); i++) { - copy.push_back(mObservers[i]); + const bool wantsPresentTime = mObservers[i]->waitForPresentTime(); + if (hasPresentTime == wantsPresentTime) { + copy.push_back(mObservers[i]); + } } } for (size_t i = 0; i < copy.size(); i++) { diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp index 5b3e65648981..e5d5e75d0f3b 100644 --- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp @@ -35,7 +35,9 @@ static JNIEnv* getenv(JavaVM* vm) { return env; } -HardwareRendererObserver::HardwareRendererObserver(JavaVM *vm, jobject observer) : mVm(vm) { +HardwareRendererObserver::HardwareRendererObserver(JavaVM* vm, jobject observer, + bool waitForPresentTime) + : uirenderer::FrameMetricsObserver(waitForPresentTime), mVm(vm) { mObserverWeak = getenv(mVm)->NewWeakGlobalRef(observer); LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr, "unable to create frame stats observer reference"); @@ -86,14 +88,16 @@ void HardwareRendererObserver::notify(const int64_t* stats) { } static jlong android_graphics_HardwareRendererObserver_createObserver(JNIEnv* env, - jobject observerObj) { + jobject observerObj, + jboolean waitForPresentTime) { JavaVM* vm = nullptr; if (env->GetJavaVM(&vm) != JNI_OK) { LOG_ALWAYS_FATAL("Unable to get Java VM"); return 0; } - HardwareRendererObserver* observer = new HardwareRendererObserver(vm, observerObj); + HardwareRendererObserver* observer = + new HardwareRendererObserver(vm, observerObj, waitForPresentTime); return reinterpret_cast<jlong>(observer); } @@ -110,10 +114,10 @@ static jint android_graphics_HardwareRendererObserver_getNextBuffer(JNIEnv* env, } static const std::array gMethods = { - MAKE_JNI_NATIVE_METHOD("nCreateObserver", "()J", - android_graphics_HardwareRendererObserver_createObserver), - MAKE_JNI_NATIVE_METHOD("nGetNextBuffer", "(J[J)I", - android_graphics_HardwareRendererObserver_getNextBuffer), + MAKE_JNI_NATIVE_METHOD("nCreateObserver", "(Z)J", + android_graphics_HardwareRendererObserver_createObserver), + MAKE_JNI_NATIVE_METHOD("nGetNextBuffer", "(J[J)I", + android_graphics_HardwareRendererObserver_getNextBuffer), }; int register_android_graphics_HardwareRendererObserver(JNIEnv* env) { diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h index 62111fd7d7a1..d3076140541b 100644 --- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h +++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h @@ -26,7 +26,7 @@ namespace android { */ class HardwareRendererObserver : public uirenderer::FrameMetricsObserver { public: - HardwareRendererObserver(JavaVM *vm, jobject observer); + HardwareRendererObserver(JavaVM* vm, jobject observer, bool waitForPresentTime); ~HardwareRendererObserver(); /** diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index f69ddacf7ca1..9793300b406d 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -599,10 +599,41 @@ void CanvasContext::finishFrame(FrameInfo* frameInfo) { // TODO (b/169858044): Move this into JankTracker to adjust deadline when queue is // double-stuffed. if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) { - mFrameMetricsReporter->reportFrameMetrics(frameInfo->data()); + mFrameMetricsReporter->reportFrameMetrics(frameInfo->data(), false /*hasPresentTime*/); } } +void CanvasContext::reportMetricsWithPresentTime() { + if (mFrameMetricsReporter == nullptr) { + return; + } + if (mNativeSurface == nullptr) { + return; + } + FrameInfo* forthBehind; + int64_t frameNumber; + { // acquire lock + std::scoped_lock lock(mLast4FrameInfosMutex); + if (mLast4FrameInfos.size() != mLast4FrameInfos.capacity()) { + // Not enough frames yet + return; + } + // Surface object keeps stats for the last 8 frames. + std::tie(forthBehind, frameNumber) = mLast4FrameInfos.front(); + } // release lock + + nsecs_t presentTime = 0; + native_window_get_frame_timestamps( + mNativeSurface->getNativeWindow(), frameNumber, nullptr /*outRequestedPresentTime*/, + nullptr /*outAcquireTime*/, nullptr /*outLatchTime*/, + nullptr /*outFirstRefreshStartTime*/, nullptr /*outLastRefreshStartTime*/, + nullptr /*outGpuCompositionDoneTime*/, &presentTime, nullptr /*outDequeueReadyTime*/, + nullptr /*outReleaseTime*/); + + forthBehind->set(FrameInfoIndex::DisplayPresentTime) = presentTime; + mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/); +} + void CanvasContext::onSurfaceStatsAvailable(void* context, ASurfaceControl* control, ASurfaceControlStats* stats) { @@ -624,6 +655,9 @@ void CanvasContext::onSurfaceStatsAvailable(void* context, ASurfaceControl* cont } } } + + instance->reportMetricsWithPresentTime(); + if (frameInfo != nullptr) { if (gpuCompleteTime == -1) { gpuCompleteTime = frameInfo->get(FrameInfoIndex::SwapBuffersCompleted); diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 2e7b2f618a8a..74f426ead912 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -219,6 +219,12 @@ private: SkRect computeDirtyRect(const Frame& frame, SkRect* dirty); void finishFrame(FrameInfo* frameInfo); + /** + * Invoke 'reportFrameMetrics' on the last frame stored in 'mLast4FrameInfos'. + * Populate the 'presentTime' field before calling. + */ + void reportMetricsWithPresentTime(); + // The same type as Frame.mWidth and Frame.mHeight int32_t mLastFrameWidth = 0; int32_t mLastFrameHeight = 0; diff --git a/location/java/android/location/CorrelationVector.java b/location/java/android/location/CorrelationVector.java index eca35dd69362..4b6e6882b50a 100644 --- a/location/java/android/location/CorrelationVector.java +++ b/location/java/android/location/CorrelationVector.java @@ -17,7 +17,6 @@ package android.location; import android.annotation.FloatRange; -import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; @@ -39,7 +38,7 @@ public final class CorrelationVector implements Parcelable { private final double mSamplingWidthMeters; private final double mSamplingStartMeters; - private final int mFrequencyOffsetMetersPerSecond; + private final double mFrequencyOffsetMetersPerSecond; @NonNull private final int[] mMagnitude; /** @@ -66,8 +65,8 @@ public final class CorrelationVector implements Parcelable { /** * Returns the frequency offset from reported pseudorange rate for this CorrelationVector. */ - @IntRange(from = 0) - public int getFrequencyOffsetMetersPerSecond() { + @FloatRange(from = 0.0f) + public double getFrequencyOffsetMetersPerSecond() { return mFrequencyOffsetMetersPerSecond; } @@ -88,7 +87,7 @@ public final class CorrelationVector implements Parcelable { Preconditions.checkNotNull(builder.mMagnitude, "Magnitude array must not be null"); Preconditions.checkArgumentPositive(builder.mMagnitude.length, "Magnitude array must have non-zero length"); - Preconditions.checkArgumentNonNegative(builder.mFrequencyOffsetMetersPerSecond, + Preconditions.checkArgument(builder.mFrequencyOffsetMetersPerSecond >= 0.0, "FrequencyOffsetMetersPerSecond must be non-negative (greater than or equal to 0)"); Preconditions.checkArgument(builder.mSamplingWidthMeters > 0.0, "SamplingWidthMeters must be positive (greater than 0)"); @@ -103,7 +102,7 @@ public final class CorrelationVector implements Parcelable { private CorrelationVector(Parcel in) { mSamplingWidthMeters = in.readDouble(); mSamplingStartMeters = in.readDouble(); - mFrequencyOffsetMetersPerSecond = in.readInt(); + mFrequencyOffsetMetersPerSecond = in.readDouble(); mMagnitude = new int[in.readInt()]; in.readIntArray(mMagnitude); } @@ -144,7 +143,7 @@ public final class CorrelationVector implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeDouble(mSamplingWidthMeters); dest.writeDouble(mSamplingStartMeters); - dest.writeInt(mFrequencyOffsetMetersPerSecond); + dest.writeDouble(mFrequencyOffsetMetersPerSecond); dest.writeInt(mMagnitude.length); dest.writeIntArray(mMagnitude); } @@ -165,7 +164,7 @@ public final class CorrelationVector implements Parcelable { return Arrays.equals(mMagnitude, c.getMagnitude()) && Double.compare(mSamplingWidthMeters, c.getSamplingWidthMeters()) == 0 && Double.compare(mSamplingStartMeters, c.getSamplingStartMeters()) == 0 - && Integer.compare(mFrequencyOffsetMetersPerSecond, + && Double.compare(mFrequencyOffsetMetersPerSecond, c.getFrequencyOffsetMetersPerSecond()) == 0; } @@ -182,7 +181,7 @@ public final class CorrelationVector implements Parcelable { private double mSamplingWidthMeters; private double mSamplingStartMeters; - private int mFrequencyOffsetMetersPerSecond; + private double mFrequencyOffsetMetersPerSecond; @NonNull private int[] mMagnitude; /** Sets the space between correlation samples in meters. */ @@ -203,7 +202,7 @@ public final class CorrelationVector implements Parcelable { /** Sets the frequency offset from reported pseudorange rate for this CorrelationVector */ @NonNull public Builder setFrequencyOffsetMetersPerSecond( - @IntRange(from = 0) int frequencyOffsetMetersPerSecond) { + @FloatRange(from = 0.0f) double frequencyOffsetMetersPerSecond) { mFrequencyOffsetMetersPerSecond = frequencyOffsetMetersPerSecond; return this; } diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index eafc6147fae8..1a67b5e7dea7 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rooi-groen)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blou-geel)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurregstelling"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Kleurregstelling stel jou in staat om te verstel hoe kleure op jou toestel vertoon word"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Totdat jy dit afskakel"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Sopas"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Foonluidspreker"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kan nie koppel nie. Skakel toestel af en weer aan"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedrade oudiotoestel"</string> <string name="help_label" msgid="3528360748637781274">"Hulp en terugvoer"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 547d0af6200d..97abce186d96 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ፕሮታኖማሊ (ቀይ-አረንጓዴ)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ትራይታኖማሊ (ሰማያዊ-ቢጫ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"የቀለም ማስተካከያ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ቀለም ማስተካከያ ቀለሞች በመሣሪያዎ ላይ እንዴት እንደሚታዩ እንዲያስተካክሉ ያስችሉዎታል"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ገደማ ቀርቷል"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"እስኪያጠፉት ድረስ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ልክ አሁን"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"የስልክ ድምጽ ማጉያ"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"መገናኘት ላይ ችግር። መሳሪያውን ያጥፉት እና እንደገና ያብሩት"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ባለገመድ የኦዲዮ መሣሪያ"</string> <string name="help_label" msgid="3528360748637781274">"እገዛ እና ግብረመልስ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index c6a1d18f9c1e..f9e12c7149c0 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"غطش الأحمر (الأحمر والأخضر)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"غمش الأزرق (الأزرق والأصفر)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"تصحيح الألوان"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"تسمح لك ميزة تصحيح الألوان بتعديل كيفية عرض الألوان على جهازك."</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا"</string> @@ -519,6 +520,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"إلى أن يتم إيقاف الوضع"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"للتو"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"مكبر صوت الهاتف"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string> <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات والآراء"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index e9deb4641e46..efd813a010e0 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্ৰ’টানোমালি (ৰঙা-সেউজীয়া)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্ৰাইটান\'মেলী (নীলা-হালধীয়া)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ৰং শুধৰণী"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ৰং শুধৰণি সুবিধাটোৰে আপোনাক আপোনাৰ ডিভাইচত ৰংবোৰ কেনেকৈ প্ৰদর্শন কৰা হয় সেয়া মিলাবলৈ দিয়ে"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>ৰ দ্বাৰা অগ্ৰাহ্য কৰা হৈছে"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"আপুনি অফ নকৰা পর্যন্ত"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"এই মাত্ৰ"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ফ’নৰ স্পীকাৰ"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"সংযোগ হোৱাত সমস্যা হৈছে। ডিভাইচটো অফ কৰি পুনৰ অন কৰক"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"তাঁৰযুক্ত অডিঅ’ ডিভাইচ"</string> <string name="help_label" msgid="3528360748637781274">"সহায় আৰু মতামত"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index d04409cd5e56..2b0fa86499bc 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qırmızı-yaşıl)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (göy-sarı)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rəng düzəlişi"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Rəng korreksiyası sizə rənglərin cihazınızda necə göstərilməsini tənzimləmək imkanı verir"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Cihazınızda rənglərin necə göstərilməsini tənzimləyin. Bu, aşağıdakıları etmək istədikdə faydalı ola bilər:<br/><br/> <ol> <li> Rəngləri daha dəqiq görmək</li> <li> Fokuslanmaq üçün rəngləri ləğv etmək</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Deaktiv edənə qədər"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"İndicə"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon dinamiki"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string> <string name="help_label" msgid="3528360748637781274">"Yardım və rəy"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index ecd70a285bd0..b3186376ad59 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boja"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekcija boja vam omogućava da prilagodite način na koji se boje prikazuju na uređaju"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Prilagodite način na koji se boje prikazuju na uređaju. To može da bude korisno kada želite:<br/><br/> <ol> <li> da vam se boje tačnije prikazuju</li> <li> da uklonite boje kako biste se fokusirali</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -516,6 +516,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem pri povezivanju. Isključite uređaj, pa ga ponovo uključite"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string> <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index 6a3b961d1c5c..7a5aec4d3b9b 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Пратанамалія (чырвоны-зялёны)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Трытанамалія (сіні-жоўты)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Карэкцыя колеру"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Карэкцыя колеру дазволіць вам наладзіць адлюстраванне колераў на экране прылады"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Зараду хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Пакуль не выключыце"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Толькі што"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Дынамік тэлефона"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Праблема з падключэннем. Выключыце і зноў уключыце прыладу"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Правадная аўдыяпрылада"</string> <string name="help_label" msgid="3528360748637781274">"Даведка і водгукі"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index d2bf70565be9..9ff2531c0e7c 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (червено – зелено)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синьо – жълто)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекция на цветове"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Функцията „Корекция на цветове“ ви позволява да коригирате това, как цветовете се показват на устройството ви"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Коригирайте как цветовете се показват на устройството ви. Това може да бъде полезно, когато искате да:<br/><br/> <ol> <li> видите цветовете по-ясно;</li> <li> премахнете цветовете, за да се фокусирате.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"До изключване"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Току-що"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Високоговорител"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Този телефон"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"При свързването възникна проблем. Изключете устройството и го включете отново"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Аудиоустройство с кабел"</string> <string name="help_label" msgid="3528360748637781274">"Помощ и отзиви"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 3ccf0e426b77..675d1794ae1a 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্রোটানোম্যালি (লাল-সবুজ)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্রিট্যানোম্যালি (নীল-হলুদ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"রঙ সংশোধন"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ডিভাইসে রঙগুলি কেমনভাবে দেখানো হবে তা অ্যাডজাস্ট করতে \'রঙ সংশোধন করুন\' বিকল্প ব্যবহার করা যেতে পারে"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"যতক্ষণ না আপনি বন্ধ করছেন"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"এখনই"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ফোনের স্পিকার"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"কানেক্ট করতে সমস্যা হচ্ছে। ডিভাইস বন্ধ করে আবার চালু করুন"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ওয়্যার অডিও ডিভাইস"</string> <string name="help_label" msgid="3528360748637781274">"সহায়তা ও মতামত"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index f01eef340abc..97083ad15519 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ispravka boje"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Ispravka boje vam dozvoljava da prilagodite način prikazivanja boja na uređaju"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -516,6 +517,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Došlo je do problema prilikom povezivanja. Isključite, pa ponovo uključite uređaj"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string> <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string> diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml index 3fd968ba4763..9202013641ea 100644 --- a/packages/SettingsLib/res/values-ca/arrays.xml +++ b/packages/SettingsLib/res/values-ca/arrays.xml @@ -234,7 +234,7 @@ <item msgid="4433736508877934305">"Cap"</item> <item msgid="9140053004929079158">"Logcat"</item> <item msgid="3866871644917859262">"Systrace (gràfics)"</item> - <item msgid="7345673972166571060">"Pila de trucades a glGetError"</item> + <item msgid="7345673972166571060">"Pila de crides a glGetError"</item> </string-array> <string-array name="show_non_rect_clip_entries"> <item msgid="2482978351289846212">"Desactivat"</item> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 7069999fc8e7..4889220a8894 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermell-verd)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (blau-groc)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correcció de color"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correcció de color permet ajustar com es mostren els colors al teu dispositiu"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Fins que no el desactivis"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Ara mateix"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altaveu del telèfon"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Desactiva el dispositiu i torna\'l a activar."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string> <string name="help_label" msgid="3528360748637781274">"Ajuda i suggeriments"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index c677feffc384..e857e60ed224 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomálie (červená a zelená)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomálie (modrá a žlutá)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekce barev"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekce barev umožňuje upravit zobrazování barev na zařízení"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Dokud tuto funkci nevypnete"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Právě teď"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Reproduktor telefonu"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problém s připojením. Vypněte zařízení a znovu jej zapněte"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kabelové audiozařízení"</string> <string name="help_label" msgid="3528360748637781274">"Nápověda a zpětná vazba"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 84247a622740..53e21ba3abc2 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopi (rød-grøn)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopi (blå-gul)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korriger farver"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Ved hjælp af farvekorrigering kan du justere, hvordan farver ser ud på din enhed"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Indtil du deaktiverer"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Lige nu"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonens højttaler"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string> <string name="help_label" msgid="3528360748637781274">"Hjælp og feedback"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 4cc79d32b797..a4a976fcf34d 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (Rot-Grün-Sehschwäche)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (Blau-Gelb-Sehschwäche)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Farbkorrektur"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Mit der Farbkorrektur kannst du anpassen, wie Farben auf deinem Display angezeigt werden"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Bis zur Deaktivierung"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Gerade eben"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Smartphone-Lautsprecher"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus & und wieder ein."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string> <string name="help_label" msgid="3528360748637781274">"Hilfe und Feedback"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 30705a1f6f62..76faa4c13617 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Πρωτανοπία (κόκκινο-πράσινο)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Τριτανοπία (μπλε-κίτρινο)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Διόρθωση χρωμάτων"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Η διόρθωση χρωμάτων σάς επιτρέπει να ρυθμίσετε τον τρόπο εμφάνισης των χρωμάτων στη συσκευή σας"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Προσαρμόστε πώς θα εμφανίζονται τα χρώματα στη συσκευή σας. Αυτό μπορεί να είναι χρήσιμο όταν θέλετε:<br/><br/> <ol> <li> Να βλέπετε τα χρώματα με μεγαλύτερη ακρίβεια</li> <li> Να καταργήσετε τα χρώματα για να συγκεντρωθείτε</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Μέχρι την απενεργοποίηση"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Μόλις τώρα"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Ηχείο τηλεφώνου"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Αυτό το τηλέφωνο"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Πρόβλημα κατά τη σύνδεση. Απενεργοποιήστε τη συσκευή και ενεργοποιήστε την ξανά"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ενσύρματη συσκευή ήχου"</string> <string name="help_label" msgid="3528360748637781274">"Βοήθεια και σχόλια"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index b3d80abfc0a2..9a63404229a5 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Colour correction allows you to adjust how colours are displayed on your device"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string> <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index ecf97ad07c85..49271dbed6f5 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Colour correction allows you to adjust how colours are displayed on your device"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string> <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index b3d80abfc0a2..9a63404229a5 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Colour correction allows you to adjust how colours are displayed on your device"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string> <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index b3d80abfc0a2..9a63404229a5 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Colour correction allows you to adjust how colours are displayed on your device"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string> <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index c3a3f3f484fb..3476b975253f 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Color correction"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Color correction allows you to adjust how colors are displayed on your device"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colors display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colors more accurately</li> <li> Remove colors to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off & back on"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string> <string name="help_label" msgid="3528360748637781274">"Help & feedback"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index eb2a23b45e70..71cf5cbea0f2 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -220,7 +220,7 @@ <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectado actualmente"</string> <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalles del dispositivo"</string> <string name="adb_device_forget" msgid="193072400783068417">"Olvidar"</string> - <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Huellas digitales del dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string> + <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Huellas dactilares del dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string> <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Error de conexión"</string> <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Asegúrate de que <xliff:g id="DEVICE_NAME">%1$s</xliff:g> esté conectado a la red correcta."</string> <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Vincular con dispositivo"</string> @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La corrección de color te permite ajustar la manera en que se muestran los colores en el dispositivo"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que lo desactives"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Recién"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altavoz del teléfono"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Error al establecer la conexión. Apaga el dispositivo y vuelve a encenderlo."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string> <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index fe9984b701db..a7d7b215e3a8 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La corrección de color te permite ajustar cómo se muestran los colores en tu dispositivo"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que lo desactives"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"justo ahora"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altavoz del teléfono"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string> <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index c70700ddc24c..add25f839d21 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaalia (punane-roheline)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaalia (sinine-kollane)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värvide korrigeerimine"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Värvide korrigeerimine võimaldab kohandada seadmes kuvatavaid värve"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Kuni välja lülitate"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Äsja"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefoni kõlar"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem ühendamisel. Lülitage seade välja ja uuesti sisse"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Juhtmega heliseade"</string> <string name="help_label" msgid="3528360748637781274">"Abi ja tagasiside"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 09c964aa9dd1..c95d15761561 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopia (gorri-berdeak)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopia (urdin-horia)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koloreen zuzenketa"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Koloreen zuzenketaren bidez, gailuan koloreak bistaratzen diren modua doi dezakezu"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Zuk desaktibatu arte"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Oraintxe"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonoaren bozgorailua"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazoren bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string> <string name="help_label" msgid="3528360748637781274">"Laguntza eta iritziak"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 22cd6ae68de2..631ff5e3cbc4 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"قرمزدشواربینی (قرمز-سبز)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"آبیدشواربینی (آبی-زرد)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"تصحیح رنگ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"تصحیح رنگ به شما امکان میدهد نحوه نمایش رنگها را در دستگاهتان تنظیم کنید"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"تا زمانیکه آن را خاموش کنید"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"هماکنون"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"بلندگوی تلفن"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"مشکل در اتصال. دستگاه را خاموش و دوباره روشن کنید"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"دستگاه صوتی سیمی"</string> <string name="help_label" msgid="3528360748637781274">"راهنما و بازخورد"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 22dde690c3cf..7591c911b96e 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (puna-vihersokeus)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (sini-keltasokeus)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värinkorjaus"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Värinkorjauksella voit muuttaa värien näkymistä laitteellasi"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Kunnes laitat pois päältä"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Äsken"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Puhelimen kaiutin"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string> <string name="help_label" msgid="3528360748637781274">"Ohje ja palaute"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index d189f72aad65..a390257c8ce4 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu/jaune)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction des couleurs"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correction des couleurs vous permet d\'ajuster la manière dont les couleurs s\'affichent sur votre appareil"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> : <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Jusqu\'à la désactivation"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Haut-parleur du téléphone"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteingez et rallumez l\'appareil"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio à câble"</string> <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 49d7faa63a3b..8cf8c6ee5ee6 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu-jaune)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction des couleurs"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correction des couleurs vous permet d\'ajuster l\'affichage des couleurs sur votre appareil"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Jusqu\'à la désactivation"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Haut-parleur du téléphone"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteignez l\'appareil, puis rallumez-le"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio filaire"</string> <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index 0922c3dca3af..c1ba51d798f1 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (vermello-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarelo)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección da cor"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A corrección da cor permíteche axustar como se mostran as cores no dispositivo"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Ata a desactivación"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altofalante do teléfono"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Produciuse un problema coa conexión. Apaga e acende o dispositivo."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string> <string name="help_label" msgid="3528360748637781274">"Axuda e comentarios"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 10c5cc87c6da..94d83e0577bf 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"પ્રોટેનોમલી (લાલ-લીલો)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ટ્રાઇટેનોમલી(વાદળી-પીળો)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"રંગ સુધારણા"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"રંગ સુધારણા તમને તમારા ડિવાઇસ પર રંગો કેવી રીતે બતાવવામાં આવે તેની ગોઠવણી કરવાની મંજૂરી આપે છે"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"તમે બંધ ન કરો ત્યાં સુધી"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"હમણાં જ"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ફોન સ્પીકર"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"કનેક્ટ કરવામાં સમસ્યા આવી રહી છે. ડિવાઇસને બંધ કરીને ફરી ચાલુ કરો"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"વાયરવાળો ઑડિયો ડિવાઇસ"</string> <string name="help_label" msgid="3528360748637781274">"સહાય અને પ્રતિસાદ"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index ea25406b1541..835e760df1b3 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"लाल रंग पहचान न पाना (लाल-हरा)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"नीला रंग पहचान न पाना (नीला-पीला)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग में सुधार करने की सुविधा"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"रंग में सुधार करने की सुविधा, आपके डिवाइस पर दिखने वाले रंगों में बदलाव करने में मदद करती है"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"आपके डिवाइस पर रंगों के दिखने के तरीके में बदलाव करें. इससे, आपको इनमें मदद मिलेगी:<br/><br/> <ol> <li> रंगों को बेहतर तरीके से देखने में</li> <li> आसानी से फ़ोकस करने के लिए, रंग हटाने में</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"बैटरी करीब <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"जब तक आप इसे बंद नहीं करते"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"अभी-अभी"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"फ़ोन का स्पीकर"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"यह फ़ोन"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string> <string name="help_label" msgid="3528360748637781274">"सहायता और सुझाव"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 27a7a6e7891a..e99d4cb94e8b 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno – zeleno)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo – žuto)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boje"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekcija boje omogućuje vam prilagodbu načina prikazivanja boja na vašem uređaju"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -516,6 +517,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo sad"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string> <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 70a48b638506..503ee6020361 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (piros– zöld)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (kék–sárga)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Színkorrekció"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A színkorrekcióval módosíthatja a színek megjelenítésének módját az eszközön"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Kikapcsolásig"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Az imént"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon hangszórója"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string> <string name="help_label" msgid="3528360748637781274">"Súgó és visszajelzés"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index c39e966d880a..3686dd171964 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -404,7 +404,7 @@ <string name="transcode_user_control" msgid="6176368544817731314">"Չեղարկել վերակոդավորման կանխադրված կարգավորումները"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"Միացնել վերակոդավորումը"</string> <string name="transcode_default" msgid="3784803084573509491">"Ենթադրել, որ հավելվածներն աջակցում են ժամանակակից ձևաչափեր"</string> - <string name="transcode_notification" msgid="5560515979793436168">"Ցուցադրել անդրկոդավորման ծանուցումներ"</string> + <string name="transcode_notification" msgid="5560515979793436168">"Ցույց տալ տրանսկոդավորման մասին ծանուցումները"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Աշխատող ծառայություններ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ծառայություն"</string> @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Պրոտանոմալիա (կարմիր-կանաչ)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Տրիտանոմալիա (կապույտ-դեղին)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Գունաշտկում"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Գունաշտկումը թույլ է տալիս կարգավորել գույների ցուցադրումն այս սարքում"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Լիցքը կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Մինչև չանջատեք"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Հենց նոր"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Հեռախոսի բարձրախոս"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Կապի խնդիր կա: Սարքն անջատեք և նորից միացրեք:"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string> <string name="help_label" msgid="3528360748637781274">"Օգնություն և հետադարձ կապ"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 037c1b3b3e76..035be7d90e05 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koreksi warna"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Koreksi warna memungkinkan Anda untuk menyesuaikan cara warna ditampilkan pada perangkat Anda"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Sampai Anda menonaktifkannya"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Baru saja"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Speaker ponsel"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ada masalah saat menghubungkan. Nonaktifkan perangkat & aktifkan kembali"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Perangkat audio berkabel"</string> <string name="help_label" msgid="3528360748637781274">"Bantuan & masukan"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 3f8783053ba3..718b5be270a7 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Litblinda (rauðgræn)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Litblinda (blágul)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Litaleiðrétting"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Litaleiðrétting gerir þér kleift að stilla hvernig litir birtast í tækinu þínu"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Þar til þú slekkur"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Rétt í þessu"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Símahátalari"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Vandamál í tengingu. Slökktu og kveiktu á tækinu"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Snúrutengt hljómtæki"</string> <string name="help_label" msgid="3528360748637781274">"Hjálp og ábendingar"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 80ab57b66548..d2176d905b34 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalìa (rosso-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalìa (blu-giallo)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correzione del colore"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correzione del colore ti consente di regolare la visualizzazione dei colori sul tuo dispositivo"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Fino alla disattivazione"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Adesso"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altoparlante telefono"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema di connessione. Spegni e riaccendi il dispositivo"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo audio cablato"</string> <string name="help_label" msgid="3528360748637781274">"Guida e feedback"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 4355f31e3ed1..1357cae170f7 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"פרוטנומליה (אדום-ירוק)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"טריטנומליה (כחול-צהוב)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"תיקון צבע"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"תיקון צבע מאפשר לשנות את האופן שבו צבעים מוצגים במכשיר שלך"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"עד הכיבוי"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"הרגע"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"רמקול של טלפון"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string> <string name="help_label" msgid="3528360748637781274">"עזרה ומשוב"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index ea4a683dd283..4a9126f066af 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"第一色弱(赤緑)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"第三色弱(青黄)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色補正"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"色補正機能では、デバイスで色をどのように表示するかを調整できます"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"デバイスで色をどのように表示するかを調整できます。この設定は以下の場合に役立ちます。<br/><br/> <ol> <li> 色をより正確に表示したい場合</li> <li> はっきり読み取れるよう色を取り除きたい場合</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"OFF にするまで"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"たった今"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"スマートフォンのスピーカー"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"このスマートフォン"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string> <string name="help_label" msgid="3528360748637781274">"ヘルプとフィードバック"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index 5798a46e7c99..8bb6ba892e6d 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"პროტოანომალია (წითელი-მწვანე)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ტრიტანომალია (ლურჯი-ყვითელი)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ფერის კორექცია"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ფერთა კორექცია საშუალებას გაძლევთ დაარეგულიროთ, თუ როგორ გამოჩნდება ფერები თქვენს მოწყობილობაზე"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"გამორთვამდე"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ახლახან"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ტელეფონის დინამიკი"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"დაკავშირებისას წარმოიქმნა პრობლემა. გამორთეთ და კვლავ ჩართეთ მოწყობილობა"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"სადენიანი აუდიო მოწყობილობა"</string> <string name="help_label" msgid="3528360748637781274">"დახმარება და გამოხმაურება"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 5ce4e3a8f1c8..6a2c21eee17f 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (қызыл-жасыл)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсті түзету"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Түсті түзету функциясының көмегімен құрылғыңызда көрсетілетін түстерді реттеуге болады."</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Өшірілгенге дейін"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Дәл қазір"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефон динамигі"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string> <string name="help_label" msgid="3528360748637781274">"Анықтама және пікір"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index e6f2cb03439e..f4cece4aa038 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ក្រហមពណ៌បៃតង)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ពណ៌ខៀវ-លឿង)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ការកែពណ៌"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ការកែតម្រូវពណ៌អនុញ្ញាតឱ្យអ្នកកែតម្រូវរបៀបបង្ហាញពណ៌នៅលើឧបករណ៍របស់អ្នក"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"កែតម្រូវរបៀបដែលពណ៌បង្ហាញនៅលើឧបករណ៍របស់អ្នក។ ចំណុចនេះអាចមានប្រយោជន៍ នៅពេលដែលអ្នកចង់៖<br/><br/> <ol> <li> មើលឃើញពណ៌កាន់តែត្រឹមត្រូវ</li> <li> លុបពណ៌ ដើម្បីជួយអ្នកក្នុងការផ្ដោត</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"បដិសេធដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"រហូតទាល់តែអ្នកបិទ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"អម្បាញ់មិញ"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ឧបករណ៍បំពងសំឡេងទូរសព្ទ"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"ទូរសព្ទនេះ"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មានបញ្ហាក្នុងការភ្ជាប់។ បិទ រួចបើកឧបករណ៍វិញ"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍សំឡេងប្រើខ្សែ"</string> <string name="help_label" msgid="3528360748637781274">"ជំនួយ និងមតិកែលម្អ"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 561e6bed887d..a844ee6d0ad5 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -404,8 +404,7 @@ <string name="transcode_user_control" msgid="6176368544817731314">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಡೀಫಾಲ್ಟ್ಗಳನ್ನು ಅತಿಕ್ರಮಿಸಿ"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> <string name="transcode_default" msgid="3784803084573509491">"ಆ್ಯಪ್ಗಳು ಆಧುನಿಕ ಫಾರ್ಮ್ಯಾಟ್ಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ ಎಂದು ಊಹಿಸಿ"</string> - <!-- no translation found for transcode_notification (5560515979793436168) --> - <skip /> + <string name="transcode_notification" msgid="5560515979793436168">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸಿ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ಈಗ ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ಹೊಂದಿಸಿ"</string> @@ -425,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ಪ್ರೊಟನೋಮಲಿ (ಕೆಂಪು-ಹಸಿರು)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ಟ್ರಿಟನೋಮಲಿ (ನೀಲಿ-ಹಳದಿ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಬಣ್ಣಗಳನ್ನು ಹೇಗೆ ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ಹೊಂದಾಣಿಕೆ ಮಾಡಲು ಬಣ್ಣ ತಿದ್ದುಪಡಿಯು ಅವಕಾಶ ನೀಡುತ್ತದೆ"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string> @@ -516,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ಇದೀಗ"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ಫೋನ್ ಸ್ಪೀಕರ್"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string> <string name="help_label" msgid="3528360748637781274">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index cd3b8b842c66..c9960c4086be 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"적색약(적녹)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"청색약(청황)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"색상 보정"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"색상 보정을 사용하면 기기에 표시되는 색상을 조절할 수 있습니다."</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"기기에 색상이 표시되는 방식을 조정합니다. 색상을 더 정확하게 보고 싶거나 집중을 위해 일부 색상을 제거할 때 유용합니다."</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>, <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"남은 시간 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"사용 중지할 때까지"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"조금 전"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"휴대전화 스피커"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"이 휴대전화"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"연결 중에 문제가 발생했습니다. 기기를 껐다가 다시 켜 보세요."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"유선 오디오 기기"</string> <string name="help_label" msgid="3528360748637781274">"고객센터"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 1990353f80b8..4ca656798df8 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (кызыл-жашыл)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсүн тууралоо"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Түстөрдү тууралоо менен, түзмөгүңүздүн экранынын түстөрүн өзгөртө аласыз"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Бул функция өчүрүлгөнгө чейин"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Жаңы эле"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефондун динамиги"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string> <string name="help_label" msgid="3528360748637781274">"Жардам/Пикир билдирүү"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 4997ea1a82c6..176c80fbc1d6 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ສີແດງ-ສີຂຽວ)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ສີຟ້າ-ສີເຫຼືອງ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ການປັບແຕ່ງສີ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ການແກ້ໄຂສີຈະເຮັດໃຫ້ທ່ານສາມາດປັບແຕ່ງການສະແດງຜົນຂອງສີຢູ່ອຸປະກອນຂອງທ່ານໄດ້"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"ຈົນກວ່າທ່ານຈະປິດ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ຕອນນີ້"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ລຳໂພງໂທລະສັບ"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ເກີດບັນຫາໃນການເຊື່ອມຕໍ່. ປິດອຸປະກອນແລ້ວເປີດກັບຄືນມາໃໝ່"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ອຸປະກອນສຽງແບບມີສາຍ"</string> <string name="help_label" msgid="3528360748637781274">"ຊ່ວຍເຫຼືອ ແລະ ຕິຊົມ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index ec3cb0d94a51..b0ab8f449c67 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (raudona, žalia)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (mėlyna, geltona)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Spalvų taisymas"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Spalvų taisymo funkcija padės koreguoti, kaip spalvos rodomos jūsų įrenginyje"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Kol išjungsite"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Ką tik"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefono garsiakalbis"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Prisijungiant kilo problema. Išjunkite įrenginį ir vėl jį įjunkite"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Laidinis garso įrenginys"</string> <string name="help_label" msgid="3528360748637781274">"Pagalba ir atsiliepimai"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index ff9f0a1649f9..2633f13e4e34 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomālija (sarkans/zaļš)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomālija (zils/dzeltens)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Krāsu korekcija"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Izmantojot krāsu korekciju, varat koriģēt krāsu attēlojumu savā ierīcē"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> — <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -516,6 +517,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Līdz brīdim, kad izslēgsiet"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Tikko"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Tālruņa skaļrunis"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Radās problēma ar savienojuma izveidi. Izslēdziet un atkal ieslēdziet ierīci."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vadu audioierīce"</string> <string name="help_label" msgid="3528360748637781274">"Palīdzība un atsauksmes"</string> diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml index d1c74e64827f..03128c17c784 100644 --- a/packages/SettingsLib/res/values-mk/arrays.xml +++ b/packages/SettingsLib/res/values-mk/arrays.xml @@ -138,9 +138,9 @@ <item msgid="1333279807604675720">"Стерео"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> - <item msgid="1241278021345116816">"Оптимизирано за квалитет на аудиото (990 кб/с - 909 кб/с)"</item> + <item msgid="1241278021345116816">"Оптимизирано за квалитет на аудиото (990 kbps - 909 kbps)"</item> <item msgid="3523665555859696539">"Балансиран квалитет на звукот и врската (660 kb/s/606 kb/s)"</item> - <item msgid="886408010459747589">"Оптимизирано за квалитет на врската (330 кб/с - 303 кб/с)"</item> + <item msgid="886408010459747589">"Оптимизирано за квалитет на врската (330 kbps - 303 kbps)"</item> <item msgid="3808414041654351577">"Најдобар напор (приспособлива стапка на битови)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 507f65c641b2..e4173d0dcac9 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (слепило за црвена и зелена)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (слепило за сина и жолта)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција на бои"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекцијата на боите ви овозможува да го приспособите начинот на прикажување на боите на вашиот уред"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Додека не го исклучите"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Неодамнешни"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефонски звучник"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string> <string name="help_label" msgid="3528360748637781274">"Помош и повратни информации"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 8a09801502e1..3cfe47954a33 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"പ്രോട്ടാനോമലി (ചുവപ്പ്-പച്ച)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ട്രിട്ടാനോമലി (നീല-മഞ്ഞ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"നിറം ക്രമീകരിക്കൽ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"നിങ്ങളുടെ ഉപകരണത്തിൽ നിറങ്ങൾ എങ്ങനെ പ്രദർശിപ്പിക്കുന്നു എന്നത് ക്രമീകരിക്കാൻ \'നിറം ക്രമീകരിക്കൽ\' അനുവദിക്കുന്നു"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"നിങ്ങൾ ഓഫാക്കുന്നത് വരെ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ഇപ്പോൾ"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ഫോൺ സ്പീക്കർ"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"കണക്റ്റ് ചെയ്യുന്നതിൽ പ്രശ്നമുണ്ടായി. ഉപകരണം ഓഫാക്കി വീണ്ടും ഓണാക്കുക"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"വയർ മുഖേന ബന്ധിപ്പിച്ച ഓഡിയോ ഉപകരണം"</string> <string name="help_label" msgid="3528360748637781274">"സഹായവും ഫീഡ്ബാക്കും"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 27ca8f59739d..7c833f7a3a52 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномаль (улаан-ногоон)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомаль (цэнхэр-шар)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Өнгө тохируулах"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Өнгө тохируулга нь танд төхөөрөмж дээрээ өнгө хэрхэн харагдахыг тохируулах боломжийг олгодог"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Таны төхөөрөмж дээр өнгийг хэрхэн үзүүлэхийг тохируулна уу. Энэ нь таныг дараахыг хийхийг хүссэн үед хэрэгтэй байж болно:<br/><br/> <ol> <li> Өнгийг илүү оновчтой харах</li> <li> Төвлөрөхийн тулд өнгийг хасах</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Таныг унтраах хүртэл"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Дөнгөж сая"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Утасны чанга яригч"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Энэ утас"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Холбогдоход асуудал гарлаа. Төхөөрөмжийг унтраагаад дахин асаана уу"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Утастай аудио төхөөрөмж"</string> <string name="help_label" msgid="3528360748637781274">"Тусламж, санал хүсэлт"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index b6c546072473..f8d9089d88e3 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -404,8 +404,7 @@ <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिंग डीफॉल्ट ओव्हरराइड करा"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिंग सुरू करा"</string> <string name="transcode_default" msgid="3784803084573509491">"असे गृहीत धरा की, ॲप्स आधुनिक फॉरमॅटना सपोर्ट करतात"</string> - <!-- no translation found for transcode_notification (5560515979793436168) --> - <skip /> + <string name="transcode_notification" msgid="5560515979793436168">"ट्रान्सकोडिंग सूचना दाखवा"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"वेबदृश्य अंमलबजावणी"</string> @@ -425,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"क्षीण रक्तवर्णांधता (लाल-हिरवा)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"रंग दृष्टी कमतरता (निळा-पिवळा)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग सुधारणा"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"कलर इन्व्हर्जन तुमच्या डिव्हाइसवर रंग कसे प्रदर्शित केले जातात ते अॅडजस्ट करू देते"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे"</string> @@ -516,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"तुम्ही बंद करेपर्यंत"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"आत्ताच"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"फोनचा स्पीकर"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करण्यात समस्या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string> <string name="help_label" msgid="3528360748637781274">"मदत आणि फीडबॅक"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 53a4398d1b90..4df385597068 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -68,7 +68,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Memutuskan sambungan..."</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Menyambung..."</string> <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> disambungkan"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"Memasangkan..."</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"Menggandingkan..."</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Disambungkan (tiada telefon)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Disambungkan (tiada media)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Disambungkan (tiada akses mesej)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -113,7 +113,7 @@ <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Gunakan untuk pemindahan fail"</string> <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Gunakan untuk input"</string> <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Gunakan untuk Alat Bantu Dengar"</string> - <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Jadikan pasangan"</string> + <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Gandingkan"</string> <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"JADIKAN PASANGAN"</string> <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Batal"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Berpasangan memberi anda akses kepada kenalan dan sejarah panggilan apabila disambungkan."</string> @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pembetulan warna"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Pembetulan warna membolehkan anda melaraskan cara warna dipaparkan pada peranti anda"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Laraskan cara warna dipaparkan pada peranti anda. Ini boleh membantu apabila anda ingin:<br/><br/> <ol> <li> Lihat warna dengan lebih tepat</li> <li> Alih keluar warna untuk membantu anda fokus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Sehingga anda matikan"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Sebentar tadi"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Pembesar suara telefon"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefon ini"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Masalah penyambungan. Matikan & hidupkan kembali peranti"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Peranti audio berwayar"</string> <string name="help_label" msgid="3528360748637781274">"Bantuan & maklum balas"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 0fef5abf782b..f10e5393877f 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (အနီ-အစိမ်း)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (အပြာ-အဝါ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင်ပြင်ဆင်မှု"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"အရောင်အမှန်ပြင်ခြင်းက သင့်စက်ပေါ်တွင် အရောင်များပြနေပုံကို ချိန်ညှိခွင့်ပြုသည်"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည်"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"သင်ပိတ်လိုက်သည် အထိ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ယခုလေးတင်"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ဖုန်းစပီကာ"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ကြိုးတပ် အသံစက်ပစ္စည်း"</string> <string name="help_label" msgid="3528360748637781274">"အကူအညီနှင့် အကြံပြုချက်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 0ca8d51645e8..9fb68d0a30ef 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rød-grønn)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blå-gul)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Fargekorrigering"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Med fargekorrigering kan du justere hvordan farger vises på enheten din"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Til du slår av"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Nå nettopp"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonhøyttaler"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string> <string name="help_label" msgid="3528360748637781274">"Hjelp og tilbakemelding"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 75b4537f6a8f..4c847cfaa2b4 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -404,8 +404,7 @@ <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिङसम्बन्धी पूर्वनिर्धारित सेटिङ परिवर्तन गर्नुहोस्"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिङ अन गर्नुहोस्"</string> <string name="transcode_default" msgid="3784803084573509491">"एपहरूमा आधुनिक फर्म्याट प्रयोग गर्न मिल्छ भनी मान्नुहोस्"</string> - <!-- no translation found for transcode_notification (5560515979793436168) --> - <skip /> + <string name="transcode_notification" msgid="5560515979793436168">"ट्रान्सकोडिङसम्बन्धी सूचना देखाइयोस्"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string> @@ -425,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"प्रोटानेमली (रातो, हरियो)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ट्रिटानोमेली (निलो-पंहेलो)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रङ्ग सुधार"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"रंङ सच्याउने सुविधाले तपाईंलाई आफ्नो यन्त्रमा रंङहरू कसरी देखाउने भन्ने कुरा निर्धारण गर्न दिन्छ"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string> @@ -516,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"तपाईंले निष्क्रिय नपार्दासम्म"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"अहिले भर्खरै"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"फोनको स्पिकर"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"जोड्ने क्रममा समस्या भयो। यन्त्रलाई निष्क्रिय पारेर फेरि सक्रिय गर्नुहोस्"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"तारयुक्त अडियो यन्त्र"</string> <string name="help_label" msgid="3528360748637781274">"मद्दत र प्रतिक्रिया"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 71d6acc6a22b..4cb755ba468c 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rood-groen)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blauw-geel)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurcorrectie"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Met kleurcorrectie kun je aanpassen hoe kleuren op je apparaat worden weergegeven"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Aanpassen hoe kleuren worden getoond op je apparaat. In de volgende gevallen kan dit handig zijn:<br/><br/> <ol> <li> Je wilt kleuren duidelijker zien.</li> <li> Je wilt kleuren verwijderen zodat je je beter kunt focussen.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Totdat je uitschakelt"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Zojuist"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefoonspeaker"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Deze telefoon"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem bij verbinding maken. Schakel het apparaat uit en weer in."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedraad audioapparaat"</string> <string name="help_label" msgid="3528360748637781274">"Hulp en feedback"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 1d6e34f7af23..b7c93e55163c 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ପ୍ରୋଟାନୋମାଲି (ଲାଲ୍-ସବୁଜ)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ନୀଳ-ହଳଦିଆ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ରଙ୍ଗ ସଂଶୋଧନ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ଆପଣଙ୍କ ଡିଭାଇସରେ ରଙ୍ଗଗୁଡ଼ିକ କିପରି ଡିସପ୍ଲେ ହୁଏ, ତାହା ଆଡଜଷ୍ଟ କରିବାକୁ \'ରଙ୍ଗ ସଂଶୋଧନ’ ଆପଣଙ୍କୁ ଅନୁମତି ଦିଏ"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ଦ୍ୱାରା ଓଭର୍ରାଇଡ୍ କରାଯାଇଛି"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"ଆପଣ ବନ୍ଦ ନକରିବା ପର୍ଯ୍ୟନ୍ତ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ଏହିକ୍ଷଣି"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ଫୋନ୍ ସ୍ପିକର୍"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଡିଭାଇସ୍ ବନ୍ଦ କରି ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ତାରଯୁକ୍ତ ଅଡିଓ ଡିଭାଇସ୍"</string> <string name="help_label" msgid="3528360748637781274">"ସାହାଯ୍ୟ ଓ ମତାମତ"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 9d91aae0a982..896a10034383 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -404,8 +404,7 @@ <string name="transcode_user_control" msgid="6176368544817731314">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਦੀਆਂ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗਾਂ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰੋ"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string> <string name="transcode_default" msgid="3784803084573509491">"ਮੰਨ ਲਓ ਕਿ ਐਪਾਂ ਆਧੁਨਿਕ ਫਾਰਮੈਟਾਂ ਦਾ ਸਮਰਥਨ ਕਰਦੀਆਂ ਹਨ"</string> - <!-- no translation found for transcode_notification (5560515979793436168) --> - <skip /> + <string name="transcode_notification" msgid="5560515979793436168">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਸੂਚਨਾਵਾਂ ਦਿਖਾਓ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲ"</string> @@ -425,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ਲਾਲ-ਹਰਾ)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ਨੀਲਾ-ਪੀਲਾ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ਰੰਗ ਸੁਧਾਈ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ਰੰਗ ਸੁਧਾਈ ਨਾਲ ਤੁਹਾਨੂੰ ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਰੰਗਾਂ ਦੇ ਪ੍ਰਦਰਸ਼ਿਤ ਹੋਣ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰਨ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string> @@ -516,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ਹੁਣੇ ਹੀ"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ਫ਼ੋਨ ਦਾ ਸਪੀਕਰ"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ। ਡੀਵਾਈਸ ਨੂੰ ਬੰਦ ਕਰਕੇ ਵਾਪਸ ਚਾਲੂ ਕਰੋ"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ਤਾਰ ਵਾਲਾ ਆਡੀਓ ਡੀਵਾਈਸ"</string> <string name="help_label" msgid="3528360748637781274">"ਮਦਦ ਅਤੇ ਵਿਚਾਰ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index f48b05f01ddc..663f3fc592da 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (czerwony-zielony)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (niebieski-żółty)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcja kolorów"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekcja kolorów pozwala na dostosowanie sposobu wyświetlania kolorów na urządzeniu"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Dopóki nie wyłączysz"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Przed chwilą"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Głośnik telefonu"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Przewodowe urządzenie audio"</string> <string name="help_label" msgid="3528360748637781274">"Pomoc i opinie"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index b9c919129623..8eab928c7fb5 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A correção de cor permite ajustar como as cores são exibidas no dispositivo"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Até você desativar"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Alto-falante do smartphone"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string> <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 57e38c078375..f28d70a71ce7 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção da cor"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A correção da cor permite-lhe ajustar a forma como as cores são apresentadas no seu dispositivo."</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Até desativar"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altifalante do telemóvel"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string> <string name="help_label" msgid="3528360748637781274">"Ajuda e comentários"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index b9c919129623..8eab928c7fb5 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A correção de cor permite ajustar como as cores são exibidas no dispositivo"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Até você desativar"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Alto-falante do smartphone"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string> <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index c2da73c5679c..0a4e46209939 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (roșu-verde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (albastru-galben)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corecția culorii"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Folosind corecția culorii, puteți ajusta modul în care se afișează culorile pe dispozitiv"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -516,6 +517,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Până când dezactivați"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Chiar acum"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Difuzorul telefonului"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Opriți și reporniți dispozitivul."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispozitiv audio cu fir"</string> <string name="help_label" msgid="3528360748637781274">"Ajutor și feedback"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index efcce7556910..b030715da04f 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (красный/зеленый)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синий/желтый)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Коррекция цвета"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Коррекция цвета позволяет изменить настройки цветопередачи на экране устройства."</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"Уровень заряда – <xliff:g id="PERCENTAGE">%1$s</xliff:g>. <xliff:g id="TIME_STRING">%2$s</xliff:g>."</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Пока вы не отключите"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Только что"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Встроенный динамик"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string> <string name="help_label" msgid="3528360748637781274">"Справка/отзыв"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 590e0e4eded1..035a159d6e97 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"වර්ණ දුර්වලතාවය (රතු-කොළ)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"වර්ණ අන්ධතාවය (නිල්-කහ)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"වර්ණ නිවැරදි කිරීම"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"වර්ණ නිවැරදි කිරීම ඔබට ඔබේ උපාංගයෙහි වර්ණ සංදර්ශනය වන ආකාරය සීරුමාරු කිරීමට ඉඩ දේ"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ඔබගේ උපාංගයේ වර්ණ සංදර්ශනය වන ආකාරය සීරුමාරු කරන්න. මෙය ඔබට පහත දේවල් සිදු කිරීමට අවශ්ය විට ප්රයෝජනවත් විය හැකිය:<br/><br/> <ol> <li> වර්ණ වඩාත් නිවැරදිව බැලීම</li> <li> ඔබට අවධානය යොමු කිරීමට උදව් වීමට වර්ණ ඉවත් කිරීම</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ක් පමණ ඉතිරියි"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"ඔබ ක්රියාවිරහිත කරන තුරු"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"මේ දැන්"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"දුරකථන ස්පීකරය"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"මෙම දුරකථනය"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"සම්බන්ධ කිරීමේ ගැටලුවකි උපාංගය ක්රියාවිරහිත කර & ආපසු ක්රියාත්මක කරන්න"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"රැහැන්ගත කළ ඕඩියෝ උපාංගය"</string> <string name="help_label" msgid="3528360748637781274">"උදවු & ප්රතිපෝෂණ"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index c817ed0e200c..d9d53515351f 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (červená a zelená)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (modrá a žltá)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Úprava farieb"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Úprava farieb umožňuje nastaviť spôsob zobrazovania farieb vo vašom zariadení"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Dokým funkciu nevypnete"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Teraz"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Reproduktor telefónu"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string> <string name="help_label" msgid="3528360748637781274">"Pomocník a spätná väzba"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 464b235e90da..81b1b60ac7fd 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (rdeča – zelena)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (modra – rumena)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Popravljanje barv"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Popravljanje barv vam omogoča prilagajanje prikaza barv v napravi"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Dokler ne izklopite"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Pravkar"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvočnik telefona"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žična zvočna naprava"</string> <string name="help_label" msgid="3528360748637781274">"Pomoč in povratne informacije"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index a2a63e165a96..b71e51f35bb4 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (e kuqe - e gjelbër)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (e kaltër - e verdhë)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korrigjimi i ngjyrës"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korrigjimi i ngjyrave të lejon të rregullosh mënyrën se si shfaqen ngjyrat në pajisjen tënde"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Deri sa ta çaktivizosh"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Pikërisht tani"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altoparlanti i telefonit"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem me lidhjen. Fike dhe ndize përsëri pajisjen"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Pajisja audio me tel"</string> <string name="help_label" msgid="3528360748637781274">"Ndihma dhe komentet"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 2119303410e0..4f37180c7f7e 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (црвено-зелено)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (плаво-жуто)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција боја"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекција боја вам омогућава да прилагодите начин на који се боје приказују на уређају"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Прилагодите начин на који се боје приказују на уређају. То може да буде корисно када желите:<br/><br/> <ol> <li> да вам се боје тачније приказују</li> <li> да уклоните боје како бисте се фокусирали</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -516,6 +516,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Док не искључите"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Управо"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Звучник телефона"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овај телефон"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем при повезивању. Искључите уређај, па га поново укључите"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичани аудио уређај"</string> <string name="help_label" msgid="3528360748637781274">"Помоћ и повратне информације"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index c7a21692fea6..2ec2ded3d34f 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rött-grönt)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blått-gult)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Färgkorrigering"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Med färgkorrigering kan du ändra hur färger visas på enheten"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Tills du inaktiverar funktionen"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Nyss"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonens högtalare"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string> <string name="help_label" msgid="3528360748637781274">"Hjälp och feedback"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 60014f437c4b..410a4aa0bddc 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (nyekundu-kijani)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (samawati-manjano)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Usahihishaji wa rangi"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Urekebishaji rangi hukuruhusu ubadilishe jinsi rangi zinavyoonyeshwa kwenye kifaa chako"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Badilisha jinsi rangi zinavyoonekana kwenye kifaa chako. Hali hii inaweza kuwa muhimu unapotaka:<br/><br/> <ol> <li> Kuona rangi kwa usahihi zaidi</li> <li> Kuondoa rangi ili kukusaidia kuwa makini</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Hadi utakapoizima"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Sasa hivi"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Spika ya simu"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Simu hii"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kuna tatizo la kuunganisha kwenye Intaneti. Zima kisha uwashe kifaa"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kifaa cha sauti kinachotumia waya"</string> <string name="help_label" msgid="3528360748637781274">"Usaidizi na maoni"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 82cce1275b10..14eb25d36a64 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"நிறம் அடையாளங்காண முடியாமை (சிவப்பு-பச்சை)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"நிறம் அடையாளங்காண முடியாமை (நீலம்-மஞ்சள்)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"வண்ணத்திருத்தம்"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"கலர் கரெக்ஷனைப் பயன்படுத்தி உங்கள் சாதனத்தில் வண்ணங்கள் காண்பிக்கப்படும் விதத்தைச் சரிசெய்யலாம்"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"ஆஃப் செய்யும் வரை"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"சற்றுமுன்"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"மொபைல் ஸ்பீக்கர்"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"இணைப்பதில் சிக்கல். சாதனத்தை ஆஃப் செய்து மீண்டும் ஆன் செய்யவும்"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"வயருடன்கூடிய ஆடியோ சாதனம்"</string> <string name="help_label" msgid="3528360748637781274">"உதவியும் கருத்தும்"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 3b04eb402585..e652ab71bba3 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"కలర్ సరిచేయడం"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"\'కలర్ సరిచేయడం\' అనే ఫీచర్ సాయంతో, మీ పరికరంలో రంగులు కనిపించే పద్ధతిని మీరు మార్చగలుగుతారు"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"మీరు ఆఫ్ చేసే వరకు"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ఇప్పుడే"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ఫోన్ స్పీకర్"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string> <string name="help_label" msgid="3528360748637781274">"సహాయం & ఫీడ్బ్యాక్"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index a9703213813e..4bd7b6ddd21e 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ตาบอดจางสีแดง (สีแดง/เขียว)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ตาบอดจางสีน้ำเงิน (สีน้ำเงิน/เหลือง)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"การแก้สี"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"การแก้สีช่วยให้คุณปรับการแสดงสีในอุปกรณ์ได้"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ปรับวิธีแสดงสีในอุปกรณ์ การดำเนินการนี้จะเป็นประโยชน์เมื่อคุณต้องการดังนี้<br/><br/> <ol> <li> เห็นสีได้ถูกต้องยิ่งขึ้น</li> <li> นำสีออกเพื่อช่วยให้เห็นชัดเจนยิ่งขึ้น</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"จนกว่าคุณจะปิด"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"เมื่อสักครู่"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ลำโพงโทรศัพท์"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"โทรศัพท์เครื่องนี้"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"เกิดปัญหาในการเชื่อมต่อ ปิดอุปกรณ์แล้วเปิดใหม่อีกครั้ง"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"อุปกรณ์เสียงแบบมีสาย"</string> <string name="help_label" msgid="3528360748637781274">"ความช่วยเหลือและความคิดเห็น"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index bedd00511118..e56e5b9b6077 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (pula-berde)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (asul-dilaw)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pagtatama ng kulay"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Nagbibigay-daan sa iyo ang pagtatama ng kulay na maisaayos kung paano ipinapakita ang mga kulay sa iyong device"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Isaayos kung paano ipinapakita ang mga kulay sa iyong device. Makakatulong ito kapag gusto mong:<br/><br/> <ol> <li> Makakita ng mas tumpak na mga kulay</li> <li> Mag-alis ng mga kulay para matulungan kang mag-focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Hanggang sa i-off mo"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Ngayon lang"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Speaker ng telepono"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ang teleponong ito"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Nagkaproblema sa pagkonekta. I-off at pagkatapos ay i-on ang device"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired na audio device"</string> <string name="help_label" msgid="3528360748637781274">"Tulong at feedback"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 2b2b44e0f9dc..5fbf5d41e40b 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (kırmızı-yeşil)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (mavi-sarı)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Renk düzeltme"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Renk düzeltme, renklerin cihazınızda nasıl görüntüleneceğini düzenlemenize olanak sağlar."</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Siz kapatana kadar"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Az önce"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon hoparlörü"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Bağlanırken sorun oluştu. Cihazı kapatıp tekrar açın"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kablolu ses cihazı"</string> <string name="help_label" msgid="3528360748637781274">"Yardım ve geri bildirim"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 9c5e2aa858aa..4511a4bc9ab5 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалія (червоний – зелений)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалія (синій – жовтий)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекція кольору"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекція кольору дає змогу регулювати відтінки зображення на екрані пристрою"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -517,6 +518,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Доки не вимкнути"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Щойно"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Динамік телефона"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string> <string name="help_label" msgid="3528360748637781274">"Довідка й відгуки"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index ee06623240de..e61d281a025f 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (سرخ سبز)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (نیلا پیلا)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"رنگ کی اصلاح"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"رنگ کی اصلاح آپ کو یہ ایڈجسٹ کرنے کی سہولت دیتی ہے کہ آپ کے آلے پر رنگ کیسے ڈسپلے کئے جاتے ہیں"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"یہاں تک کہ آپ آف کر دیں"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"ابھی ابھی"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"فون اسپیکر"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"منسلک کرنے میں مسئلہ پیش آ گیا۔ آلہ کو آف اور بیک آن کریں"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"وائرڈ آڈیو آلہ"</string> <string name="help_label" msgid="3528360748637781274">"مدد اور تاثرات"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 29c0f91c4e60..0730c6cc1b50 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qizil/yashil)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (ko‘k/sariq)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rangni tuzatish"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Ranglarni tuzatish orqali qurilmangizda ranglar qanday chiqishini tuzatish mumkin"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Qurilmadagi ranglar qanday chiqishini moslash Bu quyidagi amallarni bajarishga yordam beradi:<br/><br/> <ol> <li> Ranglarni yanada aniq koʻrish</li> <li> Diqqatni jamlash uchun ranglarni olib tashlash</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Rejimdan chiqilgunicha"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Hozir"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon karnayi"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Shu telefon"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string> <string name="help_label" msgid="3528360748637781274">"Yordam/fikr-mulohaza"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 39beecd0a87a..148ed89dc6dd 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Mù màu đỏ không hoàn toàn (đỏ-xanh lục)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mù màu (xanh lam-vàng)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Chỉnh màu"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Với chế độ chỉnh màu, bạn có thể điều chỉnh cách các màu hiển thị trên thiết bị"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Điều chỉnh cách các màu hiển thị trên thiết bị. Tùy chọn này có thể hữu ích khi bạn muốn:<br/><br/> <ol> <li> Xem các màu chính xác hơn</li> <li> Loại bỏ các màu để giúp bạn tập trung</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Cho đến khi bạn tắt"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Vừa xong"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Loa điện thoại"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"Điện thoại này"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sự cố kết nối. Hãy tắt thiết bị rồi bật lại"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Thiết bị âm thanh có dây"</string> <string name="help_label" msgid="3528360748637781274">"Trợ giúp và phản hồi"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 010a4dc9ea6c..7d1bde3d8c5c 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"借助色彩校正功能,您可以调整设备上的颜色显示方式"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"直到您将其关闭"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"刚刚"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"手机扬声器"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string> <string name="help_label" msgid="3528360748637781274">"帮助和反馈"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 1e06a91859e2..06b5cd0dfbaa 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅綠)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍黃)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"色彩校正功能讓您調整裝置顯示的顏色"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"調整裝置顯示顏色的方式。這項設定適用於以下情況:<br/><br/> <ol> <li> 想讓裝置更準確地顯示顏色</li> <li> 移除顏色以提高專注力</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"直至您關閉為止"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"手機喇叭"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音響裝置"</string> <string name="help_label" msgid="3528360748637781274">"說明與意見反映"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 2c077e7991be..dcfc59934dd8 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -424,7 +424,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅-綠)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍-黃)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"色彩校正可讓你調整裝置上顯示的顏色"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"調整裝置顯示顏色的方式。這項設定適用於以下情況:<br/><br/> <ol> <li> 想讓裝置更準確地顯示顏色</li> <li> 移除顏色以提高專注力</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -515,6 +515,7 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"直到你關閉為止"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"手機喇叭"</string> + <string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連線,請關閉裝置後再重新開啟"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音訊裝置"</string> <string name="help_label" msgid="3528360748637781274">"說明與意見回饋"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 87cf75b0beaf..2297cbe77fac 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -424,7 +424,8 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"I-Protanomaly (bomvu-luhlaza)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"I-Tritanomaly (luhlaza okwesibhakabhaka-phuzi)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ukulungiswa kombala"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Ukulungisa umbala kukuvumela ukuthi ulungise indlela imibala eboniswa ngayo kudivayisi yakho"</string> + <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (8625527799885140826) --> + <skip /> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele"</string> @@ -515,6 +516,8 @@ <string name="zen_mode_forever" msgid="3339224497605461291">"Uze uvale isikrini"</string> <string name="time_unit_just_now" msgid="3006134267292728099">"Khona manje"</string> <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Isipikha sefoni"</string> + <!-- no translation found for media_transfer_this_phone (7194341457812151531) --> + <skip /> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Inkinga yokuxhumeka. Vala idivayisi futhi uphinde uyivule"</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Idivayisi yomsindo enentambo"</string> <string name="help_label" msgid="3528360748637781274">"Usizo nempendulo"</string> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 0687191c5461..8fe6ce839ef4 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -407,7 +407,6 @@ <!-- Permission required for GTS test - GtsAssistIntentTestCases --> <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" /> <uses-permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD" /> - <uses-permission android:name="android.permission.BIND_VOICE_INTERACTION" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> <uses-permission android:name="android.permission.BIND_RESUME_ON_REBOOT_SERVICE" /> @@ -421,6 +420,9 @@ <!-- Permission required for CTS test - CtsGameManagerTestCases --> <uses-permission android:name="android.permission.MANAGE_GAME_MODE" /> + <!-- Permission required for CTS test - ClipboardManagerTest --> + <uses-permission android:name="android.permission.SET_CLIP_SOURCE" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/SystemUI/res/drawable/end_guest_button_background.xml b/packages/SystemUI/res/drawable/end_guest_button_background.xml deleted file mode 100644 index 5644b657a609..000000000000 --- a/packages/SystemUI/res/drawable/end_guest_button_background.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ 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 - --> - -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <stroke - android:width="@dimen/end_guest_button_border_size" - android:color="?android:attr/colorControlHighlight" /> - <corners android:radius="@dimen/end_guest_button_corner_radius" /> -</shape> diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher.xml b/packages/SystemUI/res/layout/keyguard_user_switcher.xml index 253c03e9effb..7aafd895f723 100644 --- a/packages/SystemUI/res/layout/keyguard_user_switcher.xml +++ b/packages/SystemUI/res/layout/keyguard_user_switcher.xml @@ -30,34 +30,4 @@ android:layout_gravity="top|end" android:gravity="end" /> - <LinearLayout - android:id="@+id/end_guest_button" - android:layout_height="@dimen/end_guest_button_layout_height" - android:layout_width="wrap_content" - android:layout_gravity="center_horizontal|bottom" - android:layout_centerHorizontal="true" - android:layout_marginBottom="@dimen/end_guest_button_margin_bottom" - android:orientation="horizontal" - android:gravity="center" - android:paddingLeft="@dimen/end_guest_button_padding_horizontal" - android:paddingRight="@dimen/end_guest_button_padding_horizontal" - android:background="@drawable/end_guest_button_background" - android:visibility="gone"> - <ImageView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center" - android:src="@drawable/ic_exit_to_app" - android:background="@android:color/transparent" - android:color="?attr/wallpaperTextColor" /> - <TextView - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="center" - android:fontFamily="@*android:string/config_bodyFontFamilyMedium" - android:textColor="?attr/wallpaperTextColor" - android:textSize="13sp" - android:text="@string/guest_exit_button" /> - </LinearLayout> - </com.android.systemui.statusbar.policy.KeyguardUserSwitcherView> diff --git a/packages/SystemUI/res/layout/tv_notification_panel.xml b/packages/SystemUI/res/layout/tv_notification_panel.xml index 8f00a727b912..eae44c8bcbb8 100644 --- a/packages/SystemUI/res/layout/tv_notification_panel.xml +++ b/packages/SystemUI/res/layout/tv_notification_panel.xml @@ -20,7 +20,7 @@ android:layout_width="@dimen/tv_notification_panel_width" android:layout_height="match_parent" android:layout_gravity="end" - android:background="@color/tv_notification_background_color" + android:background="@android:color/transparent" android:orientation="vertical"> <TextView diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml index 0961f503e7d4..64c942de8875 100644 --- a/packages/SystemUI/res/values/colors_tv.xml +++ b/packages/SystemUI/res/values/colors_tv.xml @@ -34,6 +34,7 @@ <color name="tv_volume_dialog_seek_bar_fill">#FFF8F9FA</color> <color name="tv_volume_dialog_accent">#FFDADCE0</color> - <color name="tv_notification_background_color">#383838</color> + <color name="tv_notification_default_background_color">#383838</color> + <color name="tv_notification_blur_background_color">#a0383838</color> <color name="tv_notification_text_color">#FFFFFF</color> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index ea0ea5e9472a..392eb496031a 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1333,13 +1333,6 @@ <!-- Keyguard user switcher --> <dimen name="kg_user_switcher_text_size">16sp</dimen> - <!-- End guest session button --> - <dimen name="end_guest_button_layout_height">32dp</dimen> - <dimen name="end_guest_button_padding_horizontal">16dp</dimen> - <dimen name="end_guest_button_margin_bottom">96dp</dimen> - <dimen name="end_guest_button_border_size">1dp</dimen> - <dimen name="end_guest_button_corner_radius">16dp</dimen> - <!-- Opacity at which the background for the shutdown UI will be drawn. --> <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">0.95</item> diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml index 9545bfd088a0..5bd95ebc1c41 100644 --- a/packages/SystemUI/res/values/dimens_tv.xml +++ b/packages/SystemUI/res/values/dimens_tv.xml @@ -16,4 +16,5 @@ --> <resources> <dimen name="tv_notification_panel_width">360dp</dimen> + <dimen name="tv_notification_blur_radius">100dp</dimen> </resources>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index b5ded012b3bd..783f80c2ee02 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1121,9 +1121,6 @@ <!-- Name for a freshly added user [CHAR LIMIT=30] --> <string name="user_new_user_name">New user</string> - <!-- Label for button that exits guest session and clears the guest user data [CHAR LIMIT=50]--> - <string name="guest_exit_button">End guest session</string> - <!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] --> <string name="guest_exit_guest_dialog_title">Remove guest?</string> diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml index cb433f3a6009..3e090269699b 100644 --- a/packages/SystemUI/res/values/styles_tv.xml +++ b/packages/SystemUI/res/values/styles_tv.xml @@ -30,5 +30,6 @@ <item name="android:backgroundDimEnabled">false</item> <item name="android:windowNoTitle">true</item> <item name="android:windowContentOverlay">@null</item> + <item name="android:windowIsFloating">true</item> </style> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 4bf27e2aa4b8..c46cc4f9aa0a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -71,7 +71,7 @@ public class RotationLockTile extends QSTileImpl<BooleanState> { @Override public Intent getLongClickIntent() { - return new Intent(Settings.ACTION_DISPLAY_SETTINGS); + return new Intent(Settings.ACTION_AUTO_ROTATE_SETTINGS); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java index 8fc2830aa422..bc8adc9dad5b 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java @@ -41,6 +41,7 @@ import com.google.common.util.concurrent.ListenableFuture; import java.io.File; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.time.Duration; @@ -110,6 +111,39 @@ class ImageExporter { } /** + * Stores the given Bitmap to a temp file. + */ + ListenableFuture<File> exportAsTempFile(Executor executor, Bitmap bitmap) { + return CallbackToFutureAdapter.getFuture( + (completer) -> { + executor.execute(() -> { + File cachePath; + try { + cachePath = File.createTempFile("long_screenshot_cache_", ".tmp"); + try (FileOutputStream stream = new FileOutputStream(cachePath)) { + bitmap.compress(mCompressFormat, mQuality, stream); + } catch (IOException e) { + if (cachePath.exists()) { + //noinspection ResultOfMethodCallIgnored + cachePath.delete(); + cachePath = null; + } + completer.setException(e); + } + if (cachePath != null) { + completer.set(cachePath); + } + } catch (IOException e) { + // Failed to create a new file + completer.setException(e); + } + }); + return "Bitmap#compress"; + } + ); + } + + /** * Export the image using the given executor. * * @param executor the thread for execution @@ -122,7 +156,7 @@ class ImageExporter { } /** - * Export the image using the given executor. + * Export the image to MediaStore and publish. * * @param executor the thread for execution * @param bitmap the bitmap to export @@ -131,8 +165,10 @@ class ImageExporter { */ ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime) { - final Task task = - new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat, mQuality); + + final Task task = new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat, + mQuality, /* publish */ true); + return CallbackToFutureAdapter.getFuture( (completer) -> { executor.execute(() -> { @@ -147,12 +183,36 @@ class ImageExporter { ); } + /** + * Delete the entry. + * + * @param executor the thread for execution + * @param uri the uri of the image to publish + * + * @return a listenable future result + */ + ListenableFuture<Result> delete(Executor executor, Uri uri) { + return CallbackToFutureAdapter.getFuture((completer) -> { + executor.execute(() -> { + mResolver.delete(uri, null); + + Result result = new Result(); + result.uri = uri; + result.deleted = true; + completer.set(result); + }); + return "ContentResolver#delete"; + }); + } + static class Result { + Uri uri; UUID requestId; String fileName; long timestamp; - Uri uri; CompressFormat format; + boolean published; + boolean deleted; } private static class Task { @@ -163,9 +223,10 @@ class ImageExporter { private final CompressFormat mFormat; private final int mQuality; private final String mFileName; + private final boolean mPublish; Task(ContentResolver resolver, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime, - CompressFormat format, int quality) { + CompressFormat format, int quality, boolean publish) { mResolver = resolver; mRequestId = requestId; mBitmap = bitmap; @@ -173,6 +234,7 @@ class ImageExporter { mFormat = format; mQuality = quality; mFileName = createFilename(mCaptureTime, mFormat); + mPublish = publish; } public Result execute() throws ImageExportException, InterruptedException { @@ -186,16 +248,21 @@ class ImageExporter { start = Instant.now(); } - uri = createEntry(mFormat, mCaptureTime, mFileName); + uri = createEntry(mResolver, mFormat, mCaptureTime, mFileName); throwIfInterrupted(); - writeImage(mBitmap, mFormat, mQuality, uri); + writeImage(mResolver, mBitmap, mFormat, mQuality, uri); throwIfInterrupted(); - writeExif(uri, mRequestId, mBitmap.getWidth(), mBitmap.getHeight(), mCaptureTime); + int width = mBitmap.getWidth(); + int height = mBitmap.getHeight(); + writeExif(mResolver, uri, mRequestId, width, height, mCaptureTime); throwIfInterrupted(); - publishEntry(uri); + if (mPublish) { + publishEntry(mResolver, uri); + result.published = true; + } result.timestamp = mCaptureTime.toInstant().toEpochMilli(); result.requestId = mRequestId; @@ -218,88 +285,89 @@ class ImageExporter { return result; } - Uri createEntry(CompressFormat format, ZonedDateTime time, String fileName) - throws ImageExportException { - Trace.beginSection("ImageExporter_createEntry"); - try { - final ContentValues values = createMetadata(time, format, fileName); + @Override + public String toString() { + return "export [" + mBitmap + "] to [" + mFormat + "] at quality " + mQuality; + } + } - Uri uri = mResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); - if (uri == null) { - throw new ImageExportException(RESOLVER_INSERT_RETURNED_NULL); - } - return uri; - } finally { - Trace.endSection(); + private static Uri createEntry(ContentResolver resolver, CompressFormat format, + ZonedDateTime time, String fileName) throws ImageExportException { + Trace.beginSection("ImageExporter_createEntry"); + try { + final ContentValues values = createMetadata(time, format, fileName); + + Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + if (uri == null) { + throw new ImageExportException(RESOLVER_INSERT_RETURNED_NULL); } + return uri; + } finally { + Trace.endSection(); } + } - void writeImage(Bitmap bitmap, CompressFormat format, int quality, - Uri contentUri) throws ImageExportException { - Trace.beginSection("ImageExporter_writeImage"); - try (OutputStream out = mResolver.openOutputStream(contentUri)) { - long start = SystemClock.elapsedRealtime(); - if (!bitmap.compress(format, quality, out)) { - throw new ImageExportException(IMAGE_COMPRESS_RETURNED_FALSE); - } else if (LogConfig.DEBUG_STORAGE) { - Log.d(TAG, "Bitmap.compress took " - + (SystemClock.elapsedRealtime() - start) + " ms"); - } - } catch (IOException ex) { - throw new ImageExportException(OPEN_OUTPUT_STREAM_EXCEPTION, ex); - } finally { - Trace.endSection(); + private static void writeImage(ContentResolver resolver, Bitmap bitmap, CompressFormat format, + int quality, Uri contentUri) throws ImageExportException { + Trace.beginSection("ImageExporter_writeImage"); + try (OutputStream out = resolver.openOutputStream(contentUri)) { + long start = SystemClock.elapsedRealtime(); + if (!bitmap.compress(format, quality, out)) { + throw new ImageExportException(IMAGE_COMPRESS_RETURNED_FALSE); + } else if (LogConfig.DEBUG_STORAGE) { + Log.d(TAG, "Bitmap.compress took " + + (SystemClock.elapsedRealtime() - start) + " ms"); } + } catch (IOException ex) { + throw new ImageExportException(OPEN_OUTPUT_STREAM_EXCEPTION, ex); + } finally { + Trace.endSection(); } + } - void writeExif(Uri uri, UUID requestId, int width, int height, ZonedDateTime captureTime) - throws ImageExportException { - Trace.beginSection("ImageExporter_writeExif"); - ParcelFileDescriptor pfd = null; + private static void writeExif(ContentResolver resolver, Uri uri, UUID requestId, int width, + int height, ZonedDateTime captureTime) throws ImageExportException { + Trace.beginSection("ImageExporter_writeExif"); + ParcelFileDescriptor pfd = null; + try { + pfd = resolver.openFile(uri, "rw", null); + if (pfd == null) { + throw new ImageExportException(RESOLVER_OPEN_FILE_RETURNED_NULL); + } + ExifInterface exif; try { - pfd = mResolver.openFile(uri, "rw", null); - if (pfd == null) { - throw new ImageExportException(RESOLVER_OPEN_FILE_RETURNED_NULL); - } - ExifInterface exif; - try { - exif = new ExifInterface(pfd.getFileDescriptor()); - } catch (IOException e) { - throw new ImageExportException(EXIF_READ_EXCEPTION, e); - } - - updateExifAttributes(exif, requestId, width, height, captureTime); - try { - exif.saveAttributes(); - } catch (IOException e) { - throw new ImageExportException(EXIF_WRITE_EXCEPTION, e); - } - } catch (FileNotFoundException e) { - throw new ImageExportException(RESOLVER_OPEN_FILE_EXCEPTION, e); - } finally { - closeQuietly(pfd); - Trace.endSection(); + exif = new ExifInterface(pfd.getFileDescriptor()); + } catch (IOException e) { + throw new ImageExportException(EXIF_READ_EXCEPTION, e); } - } - void publishEntry(Uri uri) throws ImageExportException { - Trace.beginSection("ImageExporter_publishEntry"); + updateExifAttributes(exif, requestId, width, height, captureTime); try { - ContentValues values = new ContentValues(); - values.put(MediaStore.MediaColumns.IS_PENDING, 0); - values.putNull(MediaStore.MediaColumns.DATE_EXPIRES); - final int rowsUpdated = mResolver.update(uri, values, /* extras */ null); - if (rowsUpdated < 1) { - throw new ImageExportException(RESOLVER_UPDATE_ZERO_ROWS); - } - } finally { - Trace.endSection(); + exif.saveAttributes(); + } catch (IOException e) { + throw new ImageExportException(EXIF_WRITE_EXCEPTION, e); } + } catch (FileNotFoundException e) { + throw new ImageExportException(RESOLVER_OPEN_FILE_EXCEPTION, e); + } finally { + closeQuietly(pfd); + Trace.endSection(); } + } - @Override - public String toString() { - return "compress [" + mBitmap + "] to [" + mFormat + "] at quality " + mQuality; + private static void publishEntry(ContentResolver resolver, Uri uri) + throws ImageExportException { + Trace.beginSection("ImageExporter_publishEntry"); + try { + ContentValues values = new ContentValues(); + values.put(MediaStore.MediaColumns.IS_PENDING, 0); + values.putNull(MediaStore.MediaColumns.DATE_EXPIRES); + final int rowsUpdated = resolver.update(uri, values, /* extras */ null); + if (rowsUpdated < 1) { + throw new ImageExportException(RESOLVER_UPDATE_ZERO_ROWS); + } + } finally { + Trace.endSection(); } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageLoader.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageLoader.java new file mode 100644 index 000000000000..988b93c8ca59 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageLoader.java @@ -0,0 +1,94 @@ +/* + * 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.systemui.screenshot; + +import android.annotation.Nullable; +import android.content.ContentResolver; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.ParcelFileDescriptor; + +import androidx.concurrent.futures.CallbackToFutureAdapter; + +import com.google.common.util.concurrent.ListenableFuture; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.inject.Inject; + +/** Loads images. */ +public class ImageLoader { + private final ContentResolver mResolver; + + static class Result { + @Nullable Uri uri; + @Nullable File fileName; + @Nullable Bitmap bitmap; + } + + @Inject + ImageLoader(ContentResolver resolver) { + mResolver = resolver; + } + + /** + * Loads an image via URI from ContentResolver. + * + * @param uri the identifier of the image to load + * @return a listenable future result + */ + ListenableFuture<Result> load(Uri uri) { + return CallbackToFutureAdapter.getFuture(completer -> { + Result result = new Result(); + try (InputStream in = mResolver.openInputStream(uri)) { + result.uri = uri; + result.bitmap = BitmapFactory.decodeStream(in); + completer.set(result); + } + catch (IOException e) { + completer.setException(e); + } + return "BitmapFactory#decodeStream"; + }); + } + + /** + * Loads an image by physical filesystem name. The current user must have filesystem + * permissions to read this file/path. + * + * @param file the system file path of the image to load + * @return a listenable future result + */ + ListenableFuture<Result> load(File file) { + return CallbackToFutureAdapter.getFuture(completer -> { + try (InputStream in = new BufferedInputStream(new FileInputStream(file))) { + Result result = new Result(); + result.fileName = file; + result.bitmap = BitmapFactory.decodeStream(in); + completer.set(result); + } catch (IOException e) { + completer.setException(e); + } + return "BitmapFactory#decodeStream"; + }); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java index ae3cd9996f04..6743afa3ab59 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java @@ -15,6 +15,7 @@ */ package com.android.systemui.screenshot; +import android.annotation.AnyThread; import android.graphics.Bitmap; import android.graphics.HardwareRenderer; import android.graphics.RecordingCanvas; @@ -26,6 +27,9 @@ import android.util.Log; import androidx.annotation.UiThread; +import com.android.internal.util.CallbackRegistry; +import com.android.internal.util.CallbackRegistry.NotifierCallback; + import java.util.ArrayList; import java.util.List; @@ -34,10 +38,14 @@ import java.util.List; * <p> * To display on-screen, use {@link #getDrawable()}. */ +@UiThread class ImageTileSet { private static final String TAG = "ImageTileSet"; + private CallbackRegistry<OnBoundsChangedListener, ImageTileSet, Rect> mOnBoundsListeners; + private CallbackRegistry<OnContentChangedListener, ImageTileSet, Rect> mContentListeners; + ImageTileSet(@UiThread Handler handler) { mHandler = handler; } @@ -64,15 +72,43 @@ class ImageTileSet { private OnContentChangedListener mOnContentChangedListener; private OnBoundsChangedListener mOnBoundsChangedListener; - void setOnBoundsChangedListener(OnBoundsChangedListener listener) { - mOnBoundsChangedListener = listener; - } - - void setOnContentChangedListener(OnContentChangedListener listener) { - mOnContentChangedListener = listener; + void addOnBoundsChangedListener(OnBoundsChangedListener listener) { + if (mOnBoundsListeners == null) { + mOnBoundsListeners = new CallbackRegistry<>( + new NotifierCallback<OnBoundsChangedListener, ImageTileSet, Rect>() { + @Override + public void onNotifyCallback(OnBoundsChangedListener callback, + ImageTileSet sender, + int arg, Rect newBounds) { + callback.onBoundsChanged(newBounds.left, newBounds.top, newBounds.right, + newBounds.bottom); + } + }); + } + mOnBoundsListeners.add(listener); + } + + void addOnContentChangedListener(OnContentChangedListener listener) { + if (mContentListeners == null) { + mContentListeners = new CallbackRegistry<>( + new NotifierCallback<OnContentChangedListener, ImageTileSet, Rect>() { + @Override + public void onNotifyCallback(OnContentChangedListener callback, + ImageTileSet sender, + int arg, Rect newBounds) { + callback.onContentChanged(); + } + }); + } + mContentListeners.add(listener); } + @AnyThread void addTile(ImageTile tile) { + if (!mHandler.getLooper().isCurrentThread()) { + mHandler.post(() -> addTile(tile)); + return; + } final Rect newBounds = new Rect(mBounds); final Rect newRect = tile.getLocation(); mTiles.add(tile); @@ -84,27 +120,15 @@ class ImageTileSet { notifyContentChanged(); } - void notifyContentChanged() { - if (mOnContentChangedListener == null) { - return; - } - if (mHandler.getLooper().isCurrentThread()) { - mOnContentChangedListener.onContentChanged(); - } else { - mHandler.post(() -> mOnContentChangedListener.onContentChanged()); + private void notifyContentChanged() { + if (mContentListeners != null) { + mContentListeners.notifyCallbacks(this, 0, null); } } - void notifyBoundsChanged(Rect bounds) { - if (mOnBoundsChangedListener == null) { - return; - } - if (mHandler.getLooper().isCurrentThread()) { - mOnBoundsChangedListener.onBoundsChanged( - bounds.left, bounds.top, bounds.right, bounds.bottom); - } else { - mHandler.post(() -> mOnBoundsChangedListener.onBoundsChanged( - bounds.left, bounds.top, bounds.right, bounds.bottom)); + private void notifyBoundsChanged(Rect bounds) { + if (mOnBoundsListeners != null) { + mOnBoundsListeners.notifyCallbacks(this, 0, bounds); } } @@ -180,8 +204,13 @@ class ImageTileSet { return mBounds.height(); } + @AnyThread void clear() { - if (mBounds.isEmpty()) { + if (!mHandler.getLooper().isCurrentThread()) { + mHandler.post(this::clear); + return; + } + if (mTiles.isEmpty()) { return; } mBounds.setEmpty(); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java index 9da6b8f240e9..b62e2c34ed6e 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java @@ -88,7 +88,7 @@ public class ScrollCaptureController { } private void onCaptureResult(CaptureResult result) { - Log.d(TAG, "onCaptureResult: " + result + " scrolling up: " + mScrollingUp + Log.d(TAG, "onCaptureResult: " + result + " scrolling " + (mScrollingUp ? "UP" : "DOWN") + " finish on boundary: " + mFinishOnBoundary); boolean emptyResult = result.captured.height() == 0; boolean partialResult = !emptyResult @@ -98,6 +98,7 @@ public class ScrollCaptureController { if (partialResult || emptyResult) { // Potentially reached a vertical boundary. Extend in the other direction. if (mFinishOnBoundary) { + Log.d(TAG, "Partial/empty: finished!"); finish = true; } else { // We hit a boundary, clear the tiles, capture everything in the opposite direction, @@ -105,16 +106,22 @@ public class ScrollCaptureController { mImageTileSet.clear(); mFinishOnBoundary = true; mScrollingUp = !mScrollingUp; + Log.d(TAG, "Partial/empty: cleared, switch direction to finish"); } } else { // Got the full requested result, but may have got enough bitmap data now int expectedTiles = mImageTileSet.size() + 1; - boolean hitMaxTiles = expectedTiles >= mSession.getMaxTiles(); - if (hitMaxTiles && mFinishOnBoundary) { + if (expectedTiles >= mSession.getMaxTiles()) { + Log.d(TAG, "Hit max tiles: finished"); + // If we ever hit the max tiles, we've got enough bitmap data to finish (even if we + // weren't sure we'd finish on this pass). finish = true; } else { - if (mScrollingUp) { + if (mScrollingUp && !mFinishOnBoundary) { + // During the initial scroll up, we only want to acquire the portion described + // by IDEAL_PORTION_ABOVE. if (expectedTiles >= mSession.getMaxTiles() * IDEAL_PORTION_ABOVE) { + Log.d(TAG, "Hit ideal portion above: clear and switch direction"); // We got enough above the start point, now see how far down it can go. mImageTileSet.clear(); mScrollingUp = false; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TiledImageDrawable.java b/packages/SystemUI/src/com/android/systemui/screenshot/TiledImageDrawable.java index 4ec8eb22c67a..71df369aa7b8 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/TiledImageDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/TiledImageDrawable.java @@ -38,9 +38,10 @@ public class TiledImageDrawable extends Drawable { public TiledImageDrawable(ImageTileSet tiles) { mTiles = tiles; - mTiles.setOnContentChangedListener(this::onContentChanged); + mTiles.addOnContentChangedListener(this::onContentChanged); } + private void onContentChanged() { if (mNode != null && mNode.hasDisplayList()) { mNode.discardDisplayList(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 5e8245f8e0e8..3496581b1b8a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -713,66 +713,45 @@ public class NotificationShelf extends ActivatableNotificationView implements return; } ExpandableNotificationRow row = (ExpandableNotificationRow) view; - StatusBarIconView icon = row.getShelfIcon(); NotificationIconContainer.IconState iconState = getIconState(icon); - View rowIcon = row.getShelfTransformationTarget(); - - // Let's resolve the relative positions of the icons - int iconStartPadding; - if (rowIcon != null) { - iconStartPadding = row.getRelativeStartPadding(rowIcon); - } else { - iconStartPadding = 0; + if (iconState == null) { + return; } - boolean stayingInShelf = row.isInShelf() && !row.isTransformingIntoShelf(); - - // Get the icon correctly positioned in X - // Even in RTL it's the left, since we're inverting the location in post - float shelfIconPositionX = icon.getLeft(); - shelfIconPositionX += (1.0f - icon.getIconScale()) * icon.getWidth() / 2.0f; - float iconXTranslation = NotificationUtils.interpolate( - iconStartPadding - shelfIconPositionX, - mShelfIcons.getActualPaddingStart(), - transitionAmount); - - // Let's handle the case that there's no Icon - boolean noIcon = !row.isShowingIcon(); - if (noIcon) { - // The view currently doesn't have an icon, lets transform it in! - iconXTranslation = mShelfIcons.getActualPaddingStart(); - } - if (iconState != null) { - iconState.hidden = transitionAmount == 0.0f && !iconState.isAnimating(icon); - boolean isAppearing = row.isDrawingAppearAnimation() && !row.isInShelf(); - if (isAppearing) { - iconState.hidden = true; - iconState.iconAppearAmount = 0.0f; - } - iconState.alpha = transitionAmount; - iconState.xTranslation = iconXTranslation; - if (stayingInShelf) { - iconState.iconAppearAmount = 1.0f; - iconState.alpha = 1.0f; - iconState.scaleX = 1.0f; - iconState.scaleY = 1.0f; - iconState.hidden = false; - } - if (row.isAboveShelf() - || row.showingPulsing() - || (!row.isInShelf() && (isLastChild && row.areGutsExposed() - || row.getTranslationZ() > mAmbientState.getBaseZHeight()))) { - iconState.hidden = true; - } - int backgroundColor = getBackgroundColorWithoutTint(); - int shelfColor = icon.getContrastedStaticDrawableColor(backgroundColor); - if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) { - int iconColor = row.getOriginalIconColor(); - shelfColor = NotificationUtils.interpolateColors(iconColor, shelfColor, - iconState.iconAppearAmount); - } - iconState.iconColor = shelfColor; + iconState.hidden = transitionAmount == 0.0f && !iconState.isAnimating(icon); + boolean isAppearing = row.isDrawingAppearAnimation() && !row.isInShelf(); + if (isAppearing) { + iconState.hidden = true; + iconState.iconAppearAmount = 0.0f; } + iconState.alpha = transitionAmount; + + // Fade in icons at shelf start + // This is important for conversation icons, which are badged and need x reset + iconState.xTranslation = mShelfIcons.getActualPaddingStart(); + + boolean stayingInShelf = row.isInShelf() && !row.isTransformingIntoShelf(); + if (stayingInShelf) { + iconState.iconAppearAmount = 1.0f; + iconState.alpha = 1.0f; + iconState.scaleX = 1.0f; + iconState.scaleY = 1.0f; + iconState.hidden = false; + } + if (row.isAboveShelf() + || row.showingPulsing() + || (!row.isInShelf() && (isLastChild && row.areGutsExposed() + || row.getTranslationZ() > mAmbientState.getBaseZHeight()))) { + iconState.hidden = true; + } + int backgroundColor = getBackgroundColorWithoutTint(); + int shelfColor = icon.getContrastedStaticDrawableColor(backgroundColor); + if (row.isShowingIcon() && shelfColor != StatusBarIconView.NO_COLOR) { + int iconColor = row.getOriginalIconColor(); + shelfColor = NotificationUtils.interpolateColors(iconColor, shelfColor, + iconState.iconAppearAmount); + } + iconState.iconColor = shelfColor; } private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index ae14fa943a4b..19b98953325f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -1051,9 +1051,7 @@ public class NotificationPanelViewController extends PanelViewController { .getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia(); mKeyguardStatusViewController.setHasVisibleNotifications(hasVisibleNotifications); int userIconHeight = mKeyguardQsUserSwitchController != null - ? mKeyguardQsUserSwitchController.getUserIconHeight() - : (mKeyguardUserSwitcherController != null - ? mKeyguardUserSwitcherController.getUserIconHeight() : 0); + ? mKeyguardQsUserSwitchController.getUserIconHeight() : 0; mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard, totalHeight - bottomPadding, mNotificationStackScrollLayoutController.getIntrinsicContentHeight(), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 7b2330bdcd6e..270a0f8c5d5e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -124,6 +124,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump public static final float BUSY_SCRIM_ALPHA = 1f; /** + * The default scrim under the expanded bubble stack. + * This should not be lower than 0.54, otherwise we won't pass GAR. + */ + public static final float BUBBLE_SCRIM_ALPHA = 0.6f; + + /** * Scrim opacity that can have text on top. */ public static final float GAR_SCRIM_ALPHA = 0.6f; @@ -207,8 +213,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump FeatureFlags featureFlags, @Main Executor mainExecutor) { mScrimStateListener = lightBarController::setScrimState; mDefaultScrimAlpha = featureFlags.isShadeOpaque() ? BUSY_SCRIM_ALPHA : GAR_SCRIM_ALPHA; - ScrimState.BUBBLE_EXPANDED.setBubbleAlpha(featureFlags.isShadeOpaque() - ? BUSY_SCRIM_ALPHA : GAR_SCRIM_ALPHA); + ScrimState.BUBBLE_EXPANDED.setBubbleAlpha(BUBBLE_SCRIM_ALPHA); mBlurUtils = blurUtils; mKeyguardStateController = keyguardStateController; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java index 5a80c05cc3cd..25e908450808 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java @@ -33,7 +33,6 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.LinearLayout; import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardUpdateMonitor; @@ -83,12 +82,10 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS // Child views of KeyguardUserSwitcherView private KeyguardUserSwitcherListView mListView; - private LinearLayout mEndGuestButton; // State info for the user switcher private boolean mUserSwitcherOpen; private int mCurrentUserId = UserHandle.USER_NULL; - private boolean mCurrentUserIsGuest; private int mBarState; private float mDarkAmount; @@ -185,11 +182,6 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS if (DEBUG) Log.d(TAG, "onInit"); mListView = mView.findViewById(R.id.keyguard_user_switcher_list); - mEndGuestButton = mView.findViewById(R.id.end_guest_button); - - mEndGuestButton.setOnClickListener(v -> { - mUserSwitcherController.showExitGuestDialog(mCurrentUserId); - }); mView.setOnTouchListener((v, event) -> { if (!isListAnimating()) { @@ -209,9 +201,14 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS mKeyguardUpdateMonitor.registerCallback(mInfoCallback); mStatusBarStateController.addCallback(mStatusBarStateListener); mScreenLifecycle.addObserver(mScreenObserver); - mView.addOnLayoutChangeListener(mBackground); - mView.setBackground(mBackground); - mBackground.setAlpha(0); + if (isSimpleUserSwitcher()) { + // Don't use the background for the simple user switcher + setUserSwitcherOpened(true /* open */, true /* animate */); + } else { + mView.addOnLayoutChangeListener(mBackground); + mView.setBackground(mBackground); + mBackground.setAlpha(0); + } } @Override @@ -291,7 +288,6 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS } foundCurrentUser = true; mCurrentUserId = userTag.info.id; - mCurrentUserIsGuest = userTag.isGuest; // Current user is always visible newView.updateVisibilities(true /* showItem */, mUserSwitcherOpen /* showTextName */, false /* animate */); @@ -317,19 +313,10 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS if (!foundCurrentUser) { Log.w(TAG, "Current user is not listed"); mCurrentUserId = UserHandle.USER_NULL; - mCurrentUserIsGuest = false; } } /** - * Get the height of the keyguard user switcher view when closed. - */ - public int getUserIconHeight() { - View firstChild = mListView.getChildAt(0); - return firstChild == null ? 0 : firstChild.getHeight(); - } - - /** * Set the visibility of the keyguard user switcher view based on some new state. */ public void setKeyguardUserSwitcherVisibility( @@ -406,7 +393,6 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS private void updateVisibilities(boolean animate) { if (DEBUG) Log.d(TAG, String.format("updateVisibilities: animate=%b", animate)); - mEndGuestButton.animate().cancel(); if (mBgAnimator != null) { mBgAnimator.cancel(); } @@ -434,44 +420,6 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS }); mBgAnimator.start(); } - - if (mUserSwitcherOpen && mCurrentUserIsGuest) { - // Show the "End guest session" button - mEndGuestButton.setVisibility(View.VISIBLE); - if (animate) { - mEndGuestButton.setAlpha(0f); - mEndGuestButton.animate() - .alpha(1f) - .setDuration(360) - .setInterpolator(Interpolators.ALPHA_IN) - .withEndAction(() -> { - mEndGuestButton.setClickable(true); - }); - } else { - mEndGuestButton.setClickable(true); - mEndGuestButton.setAlpha(1f); - } - } else { - // Hide the "End guest session" button. If it's already GONE, don't try to - // animate it or it will appear again for an instant. - mEndGuestButton.setClickable(false); - if (animate && mEndGuestButton.getVisibility() != View.GONE) { - mEndGuestButton.setVisibility(View.VISIBLE); - mEndGuestButton.setAlpha(1f); - mEndGuestButton.animate() - .alpha(0f) - .setDuration(360) - .setInterpolator(Interpolators.ALPHA_OUT) - .withEndAction(() -> { - mEndGuestButton.setVisibility(View.GONE); - mEndGuestButton.setAlpha(1f); - }); - } else { - mEndGuestButton.setVisibility(View.GONE); - mEndGuestButton.setAlpha(1f); - } - } - mListView.updateVisibilities(mUserSwitcherOpen, animate); } @@ -532,15 +480,6 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS return createUserDetailItemView(convertView, parent, item); } - @Override - public String getName(Context context, UserSwitcherController.UserRecord item) { - if (item.isGuest) { - return context.getString(com.android.settingslib.R.string.guest_nickname); - } else { - return super.getName(context, item); - } - } - KeyguardUserDetailItemView convertOrInflate(View convertView, ViewGroup parent) { if (!(convertView instanceof KeyguardUserDetailItemView) || !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) { @@ -608,18 +547,11 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS } if (mKeyguardUserSwitcherController.isUserSwitcherOpen()) { - if (user.isCurrent) { - // Close the switcher if tapping the current user - mKeyguardUserSwitcherController.setUserSwitcherOpened( - false /* open */, true /* animate */); - } else if (user.isSwitchToEnabled) { - if (!user.isAddUser && !user.isRestricted && !user.isDisabledByAdmin) { - if (mCurrentUserView != null) { - mCurrentUserView.setActivated(false); - } - v.setActivated(true); - } + if (!user.isCurrent || user.isGuest) { onUserListItemClicked(user); + } else { + mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple( + true /* animate */); } } else { // If switcher is closed, tapping anywhere in the view will open it diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java index 7c82c116eb3d..a815adfc9c9a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java @@ -35,20 +35,22 @@ public class KeyguardUserSwitcherListView extends AlphaOptimizedLinearLayout { private static final String TAG = "KeyguardUserSwitcherListView"; private static final boolean DEBUG = KeyguardConstants.DEBUG; - private static final int ANIMATION_DURATION_OPENING = 360; - private static final int ANIMATION_DURATION_CLOSING = 240; - private boolean mAnimating; private final AppearAnimationUtils mAppearAnimationUtils; private final DisappearAnimationUtils mDisappearAnimationUtils; public KeyguardUserSwitcherListView(Context context, AttributeSet attrs) { super(context, attrs); - setClipChildren(false); - mAppearAnimationUtils = new AppearAnimationUtils(context, ANIMATION_DURATION_OPENING, - -0.5f, 0.5f, Interpolators.FAST_OUT_SLOW_IN); - mDisappearAnimationUtils = new DisappearAnimationUtils(context, ANIMATION_DURATION_CLOSING, - 0.5f, 0.5f, Interpolators.FAST_OUT_LINEAR_IN); + mAppearAnimationUtils = new AppearAnimationUtils(context, + AppearAnimationUtils.DEFAULT_APPEAR_DURATION, + -0.5f /* translationScaleFactor */, + 0.5f /* delayScaleFactor */, + Interpolators.FAST_OUT_SLOW_IN); + mDisappearAnimationUtils = new DisappearAnimationUtils(context, + AppearAnimationUtils.DEFAULT_APPEAR_DURATION, + 0.2f /* translationScaleFactor */, + 0.2f /* delayScaleFactor */, + Interpolators.FAST_OUT_SLOW_IN_REVERSE); } /** @@ -82,69 +84,40 @@ public class KeyguardUserSwitcherListView extends AlphaOptimizedLinearLayout { mAnimating = false; - int userListCount = getChildCount(); - if (userListCount > 0) { - // The first child is always the current user. - KeyguardUserDetailItemView currentUserView = ((KeyguardUserDetailItemView) getChildAt( - 0)); - currentUserView.updateVisibilities(true /* showItem */, open /* showTextName */, - animate); - currentUserView.setClickable(true); - currentUserView.clearAnimation(); - } - - if (userListCount <= 1) { - return; - } - - if (animate) { - // Create an array of all the remaining users (that aren't the current user). - KeyguardUserDetailItemView[] otherUserViews = - new KeyguardUserDetailItemView[userListCount - 1]; - for (int i = 1, n = 0; i < userListCount; i++, n++) { - otherUserViews[n] = (KeyguardUserDetailItemView) getChildAt(i); - + int childCount = getChildCount(); + KeyguardUserDetailItemView[] userItemViews = new KeyguardUserDetailItemView[childCount]; + for (int i = 0; i < childCount; i++) { + userItemViews[i] = (KeyguardUserDetailItemView) getChildAt(i); + userItemViews[i].clearAnimation(); + if (i == 0) { + // The first child is always the current user. + userItemViews[i].updateVisibilities(true /* showItem */, open /* showTextName */, + animate); + userItemViews[i].setClickable(true); + } else { // Update clickable state immediately so that the menu feels more responsive - otherUserViews[n].setClickable(open); - + userItemViews[i].setClickable(open); // Before running the animation, ensure visibility is set correctly - otherUserViews[n].updateVisibilities( - true /* showItem */, true /* showTextName */, false /* animate */); - otherUserViews[n].clearAnimation(); + userItemViews[i].updateVisibilities(animate || open /* showItem */, + true /* showTextName */, false /* animate */); } + } + + if (animate) { + // AnimationUtils will immediately hide/show the first item in the array. Since the + // first view is the current user, we want to manage its visibility separately. + // Set first item to null so AnimationUtils ignores it. + userItemViews[0] = null; setClipChildren(false); setClipToPadding(false); - mAnimating = true; - - final int nonCurrentUserCount = otherUserViews.length; - if (open) { - mAppearAnimationUtils.startAnimation(otherUserViews, () -> { - setClipChildren(true); - setClipToPadding(true); - mAnimating = false; - }); - } else { - mDisappearAnimationUtils.startAnimation(otherUserViews, () -> { - setClipChildren(true); - setClipToPadding(true); - for (int i = 0; i < nonCurrentUserCount; i++) { - otherUserViews[i].updateVisibilities( - false /* showItem */, true /* showTextName */, false /* animate */); - } - mAnimating = false; - }); - } - } else { - for (int i = 1; i < userListCount; i++) { - KeyguardUserDetailItemView nonCurrentUserView = - ((KeyguardUserDetailItemView) getChildAt(i)); - nonCurrentUserView.clearAnimation(); - nonCurrentUserView.updateVisibilities( - open /* showItem */, true /* showTextName */, false /* animate */); - nonCurrentUserView.setClickable(open); - } + (open ? mAppearAnimationUtils : mDisappearAnimationUtils) + .startAnimation(userItemViews, () -> { + setClipChildren(true); + setClipToPadding(true); + mAnimating = false; + }); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanelActivity.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanelActivity.java index 30f401b91d25..b325b10957f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanelActivity.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanelActivity.java @@ -20,15 +20,19 @@ import android.annotation.NonNull; import android.app.Activity; import android.app.NotificationManager; import android.content.Intent; +import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.service.notification.StatusBarNotification; import android.util.SparseArray; +import android.view.Gravity; import android.view.View; import androidx.leanback.widget.VerticalGridView; import com.android.systemui.R; +import java.util.function.Consumer; + import javax.inject.Inject; /** @@ -42,6 +46,7 @@ public class TvNotificationPanelActivity extends Activity implements private VerticalGridView mNotificationListView; private View mNotificationPlaceholder; private boolean mPanelAlreadyOpen = false; + private final Consumer<Boolean> mBlurConsumer = this::enableBlur; @Inject public TvNotificationPanelActivity(TvNotificationHandler tvNotificationHandler) { @@ -103,6 +108,33 @@ public class TvNotificationPanelActivity extends Activity implements } @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + getWindow().setGravity(Gravity.END); + getWindowManager().addCrossWindowBlurEnabledListener(mBlurConsumer); + } + + private void enableBlur(boolean enabled) { + if (enabled) { + int blurRadius = getResources().getDimensionPixelSize( + R.dimen.tv_notification_blur_radius); + getWindow().setBackgroundDrawable( + new ColorDrawable(getColor(R.color.tv_notification_blur_background_color))); + getWindow().setBackgroundBlurRadius(blurRadius); + } else { + getWindow().setBackgroundDrawable( + new ColorDrawable(getColor(R.color.tv_notification_default_background_color))); + getWindow().setBackgroundBlurRadius(0); + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + getWindowManager().removeCrossWindowBlurEnabledListener(mBlurConsumer); + } + + @Override public void onDestroy() { super.onDestroy(); mTvNotificationHandler.setTvNotificationListener(null); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java index e9e4380859b7..7244ffed61b9 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java @@ -300,7 +300,7 @@ public class TunerServiceImpl extends TunerService { dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), (DialogInterface.OnClickListener) null); dialog.setButton(DialogInterface.BUTTON_POSITIVE, - mContext.getString(R.string.guest_exit_guest_dialog_remove), (d, which) -> { + mContext.getString(R.string.qs_customize_remove), (d, which) -> { // Tell the tuner (in main SysUI process) to clear all its settings. mContext.sendBroadcast(new Intent(TunerService.ACTION_CLEAR)); // Disable access to tuner. diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java index ff2881953342..82dad68f238c 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java @@ -19,16 +19,15 @@ package com.android.systemui.wmshell; import android.content.Context; import android.os.Handler; -import com.android.systemui.dagger.WMComponent; import com.android.systemui.dagger.WMSingleton; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.annotations.ShellMainThread; -import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.PipAnimationController; @@ -140,6 +139,7 @@ public abstract class TvPipModule { @Provides static PipTaskOrganizer providePipTaskOrganizer(Context context, TvPipMenuController tvPipMenuController, + SyncTransactionQueue syncTransactionQueue, PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm, PipAnimationController pipAnimationController, @@ -149,7 +149,8 @@ public abstract class TvPipModule { DisplayController displayController, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer, @ShellMainThread ShellExecutor mainExecutor) { - return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm, + return new PipTaskOrganizer(context, + syncTransactionQueue, pipBoundsState, pipBoundsAlgorithm, tvPipMenuController, pipAnimationController, pipSurfaceTransactionHelper, pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor); diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index 754b6a6435b4..d5183f85ad13 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -172,6 +172,7 @@ public class WMShellModule { @WMSingleton @Provides static PipTaskOrganizer providePipTaskOrganizer(Context context, + SyncTransactionQueue syncTransactionQueue, PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm, PhonePipMenuController menuPhoneController, @@ -182,7 +183,8 @@ public class WMShellModule { DisplayController displayController, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer, @ShellMainThread ShellExecutor mainExecutor) { - return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm, + return new PipTaskOrganizer(context, + syncTransactionQueue, pipBoundsState, pipBoundsAlgorithm, menuPhoneController, pipAnimationController, pipSurfaceTransactionHelper, pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 21368d6d5309..b1f1b5e78b5c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -542,7 +542,7 @@ public class ScrimControllerTest extends SysuiTestCase { Assert.assertEquals(ScrimController.BUSY_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.0f); // Bubble scrim should be visible - Assert.assertEquals(ScrimController.BUSY_SCRIM_ALPHA, + Assert.assertEquals(ScrimController.BUBBLE_SCRIM_ALPHA, mScrimForBubble.getViewAlpha(), 0.0f); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index f1fc0b7723fc..9b9937b9e260 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -955,8 +955,8 @@ public class BubblesTest extends SysuiTestCase { @Test public void testNotifyShadeSuppressionChange_notificationDismiss() { - Bubbles.NotificationSuppressionChangedListener listener = - mock(Bubbles.NotificationSuppressionChangedListener.class); + Bubbles.SuppressionChangedListener listener = + mock(Bubbles.SuppressionChangedListener.class); mBubbleData.setSuppressionChangedListener(listener); mEntryListener.onPendingEntryAdded(mRow.getEntry()); @@ -979,8 +979,8 @@ public class BubblesTest extends SysuiTestCase { @Test public void testNotifyShadeSuppressionChange_bubbleExpanded() { - Bubbles.NotificationSuppressionChangedListener listener = - mock(Bubbles.NotificationSuppressionChangedListener.class); + Bubbles.SuppressionChangedListener listener = + mock(Bubbles.SuppressionChangedListener.class); mBubbleData.setSuppressionChangedListener(listener); mEntryListener.onPendingEntryAdded(mRow.getEntry()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java index 9e10b21ce3b7..b0ec628b638b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java @@ -789,8 +789,8 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { @Test public void testNotifyShadeSuppressionChange_notificationDismiss() { - Bubbles.NotificationSuppressionChangedListener listener = - mock(Bubbles.NotificationSuppressionChangedListener.class); + Bubbles.SuppressionChangedListener listener = + mock(Bubbles.SuppressionChangedListener.class); mBubbleData.setSuppressionChangedListener(listener); mEntryListener.onEntryAdded(mRow.getEntry()); @@ -812,8 +812,8 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { @Test public void testNotifyShadeSuppressionChange_bubbleExpanded() { - Bubbles.NotificationSuppressionChangedListener listener = - mock(Bubbles.NotificationSuppressionChangedListener.class); + Bubbles.SuppressionChangedListener listener = + mock(Bubbles.SuppressionChangedListener.class); mBubbleData.setSuppressionChangedListener(listener); mEntryListener.onEntryAdded(mRow.getEntry()); diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java index 39efe731ce8a..806a25a748e2 100644 --- a/rs/java/android/renderscript/RenderScript.java +++ b/rs/java/android/renderscript/RenderScript.java @@ -1363,13 +1363,6 @@ public class RenderScript { mApplicationContext = ctx.getApplicationContext(); } mRWLock = new ReentrantReadWriteLock(); - try { - registerNativeAllocation.invoke(sRuntime, 4 * 1024 * 1024); // 4MB for GC sake - } catch (Exception e) { - Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e); - throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e); - } - } /** diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java index 6828dd916701..bafb641dcc9e 100644 --- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java +++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java @@ -40,34 +40,29 @@ public class ActionReplacingCallback extends IAccessibilityInteractionConnection private final IAccessibilityInteractionConnectionCallback mServiceCallback; private final IAccessibilityInteractionConnection mConnectionWithReplacementActions; private final int mInteractionId; - private final int mNodeWithReplacementActionsInteractionId; private final Object mLock = new Object(); @GuardedBy("mLock") - private boolean mReplacementNodeIsReadyOrFailed; - - @GuardedBy("mLock") - AccessibilityNodeInfo mNodeWithReplacementActions; + List<AccessibilityNodeInfo> mNodesWithReplacementActions; @GuardedBy("mLock") List<AccessibilityNodeInfo> mNodesFromOriginalWindow; @GuardedBy("mLock") - boolean mSetFindNodeFromOriginalWindowCalled = false; - - @GuardedBy("mLock") AccessibilityNodeInfo mNodeFromOriginalWindow; + // Keep track of whether or not we've been called back for a single node @GuardedBy("mLock") - boolean mSetFindNodesFromOriginalWindowCalled = false; - + boolean mSingleNodeCallbackHappened; + // Keep track of whether or not we've been called back for multiple node @GuardedBy("mLock") - List<AccessibilityNodeInfo> mPrefetchedNodesFromOriginalWindow; + boolean mMultiNodeCallbackHappened; + // We shouldn't get any more callbacks after we've called back the original service, but + // keep track to make sure we catch such strange things @GuardedBy("mLock") - boolean mSetPrefetchFromOriginalWindowCalled = false; - + boolean mDone; public ActionReplacingCallback(IAccessibilityInteractionConnectionCallback serviceCallback, IAccessibilityInteractionConnection connectionWithReplacementActions, @@ -75,20 +70,19 @@ public class ActionReplacingCallback extends IAccessibilityInteractionConnection mServiceCallback = serviceCallback; mConnectionWithReplacementActions = connectionWithReplacementActions; mInteractionId = interactionId; - mNodeWithReplacementActionsInteractionId = interactionId + 1; // Request the root node of the replacing window final long identityToken = Binder.clearCallingIdentity(); try { mConnectionWithReplacementActions.findAccessibilityNodeInfoByAccessibilityId( - AccessibilityNodeInfo.ROOT_NODE_ID, null, - mNodeWithReplacementActionsInteractionId, this, 0, + AccessibilityNodeInfo.ROOT_NODE_ID, null, interactionId + 1, this, 0, interrogatingPid, interrogatingTid, null, null); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); } - mReplacementNodeIsReadyOrFailed = true; + // Pretend we already got a (null) list of replacement nodes + mMultiNodeCallbackHappened = true; } finally { Binder.restoreCallingIdentity(identityToken); } @@ -96,67 +90,46 @@ public class ActionReplacingCallback extends IAccessibilityInteractionConnection @Override public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, int interactionId) { - synchronized (mLock) { + boolean readyForCallback; + synchronized(mLock) { if (interactionId == mInteractionId) { mNodeFromOriginalWindow = info; - mSetFindNodeFromOriginalWindowCalled = true; - } else if (interactionId == mNodeWithReplacementActionsInteractionId) { - mNodeWithReplacementActions = info; - mReplacementNodeIsReadyOrFailed = true; } else { Slog.e(LOG_TAG, "Callback with unexpected interactionId"); return; } + + mSingleNodeCallbackHappened = true; + readyForCallback = mMultiNodeCallbackHappened; + } + if (readyForCallback) { + replaceInfoActionsAndCallService(); } - replaceInfoActionsAndCallServiceIfReady(); } @Override public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos, int interactionId) { - synchronized (mLock) { + boolean callbackForSingleNode; + boolean callbackForMultipleNodes; + synchronized(mLock) { if (interactionId == mInteractionId) { mNodesFromOriginalWindow = infos; - mSetFindNodesFromOriginalWindowCalled = true; - } else if (interactionId == mNodeWithReplacementActionsInteractionId) { - setNodeWithReplacementActionsFromList(infos); - mReplacementNodeIsReadyOrFailed = true; + } else if (interactionId == mInteractionId + 1) { + mNodesWithReplacementActions = infos; } else { Slog.e(LOG_TAG, "Callback with unexpected interactionId"); return; } + callbackForSingleNode = mSingleNodeCallbackHappened; + callbackForMultipleNodes = mMultiNodeCallbackHappened; + mMultiNodeCallbackHappened = true; } - replaceInfoActionsAndCallServiceIfReady(); - } - - @Override - public void setPrefetchAccessibilityNodeInfoResult(List<AccessibilityNodeInfo> infos, - int interactionId) - throws RemoteException { - synchronized (mLock) { - if (interactionId == mInteractionId) { - mPrefetchedNodesFromOriginalWindow = infos; - mSetPrefetchFromOriginalWindowCalled = true; - } else { - Slog.e(LOG_TAG, "Callback with unexpected interactionId"); - return; - } + if (callbackForSingleNode) { + replaceInfoActionsAndCallService(); } - replaceInfoActionsAndCallServiceIfReady(); - } - - private void replaceInfoActionsAndCallServiceIfReady() { - replaceInfoActionsAndCallService(); - replaceInfosActionsAndCallService(); - replacePrefetchInfosActionsAndCallService(); - } - - private void setNodeWithReplacementActionsFromList(List<AccessibilityNodeInfo> infos) { - for (int i = 0; i < infos.size(); i++) { - AccessibilityNodeInfo info = infos.get(i); - if (info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID) { - mNodeWithReplacementActions = info; - } + if (callbackForMultipleNodes) { + replaceInfosActionsAndCallService(); } } @@ -169,81 +142,55 @@ public class ActionReplacingCallback extends IAccessibilityInteractionConnection private void replaceInfoActionsAndCallService() { final AccessibilityNodeInfo nodeToReturn; - boolean doCallback = false; synchronized (mLock) { - doCallback = mReplacementNodeIsReadyOrFailed - && mSetFindNodeFromOriginalWindowCalled; - if (doCallback && mNodeFromOriginalWindow != null) { + if (mDone) { + if (DEBUG) { + Slog.e(LOG_TAG, "Extra callback"); + } + return; + } + if (mNodeFromOriginalWindow != null) { replaceActionsOnInfoLocked(mNodeFromOriginalWindow); - mSetFindNodeFromOriginalWindowCalled = false; } + recycleReplaceActionNodesLocked(); nodeToReturn = mNodeFromOriginalWindow; + mDone = true; } - if (doCallback) { - try { - mServiceCallback.setFindAccessibilityNodeInfoResult(nodeToReturn, mInteractionId); - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfoResult"); - } + try { + mServiceCallback.setFindAccessibilityNodeInfoResult(nodeToReturn, mInteractionId); + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfoResult"); } } } private void replaceInfosActionsAndCallService() { - List<AccessibilityNodeInfo> nodesToReturn = null; - boolean doCallback = false; + final List<AccessibilityNodeInfo> nodesToReturn; synchronized (mLock) { - doCallback = mReplacementNodeIsReadyOrFailed - && mSetFindNodesFromOriginalWindowCalled; - if (doCallback) { - nodesToReturn = replaceActionsLocked(mNodesFromOriginalWindow); - mSetFindNodesFromOriginalWindowCalled = false; - } - } - if (doCallback) { - try { - mServiceCallback.setFindAccessibilityNodeInfosResult(nodesToReturn, mInteractionId); - } catch (RemoteException re) { + if (mDone) { if (DEBUG) { - Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfosResult"); + Slog.e(LOG_TAG, "Extra callback"); } + return; } - } - } - - private void replacePrefetchInfosActionsAndCallService() { - List<AccessibilityNodeInfo> nodesToReturn = null; - boolean doCallback = false; - synchronized (mLock) { - doCallback = mReplacementNodeIsReadyOrFailed - && mSetPrefetchFromOriginalWindowCalled; - if (doCallback) { - nodesToReturn = replaceActionsLocked(mPrefetchedNodesFromOriginalWindow); - mSetPrefetchFromOriginalWindowCalled = false; - } - } - if (doCallback) { - try { - mServiceCallback.setPrefetchAccessibilityNodeInfoResult( - nodesToReturn, mInteractionId); - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfosResult"); + if (mNodesFromOriginalWindow != null) { + for (int i = 0; i < mNodesFromOriginalWindow.size(); i++) { + replaceActionsOnInfoLocked(mNodesFromOriginalWindow.get(i)); } } + recycleReplaceActionNodesLocked(); + nodesToReturn = (mNodesFromOriginalWindow == null) + ? null : new ArrayList<>(mNodesFromOriginalWindow); + mDone = true; } - } - - @GuardedBy("mLock") - private List<AccessibilityNodeInfo> replaceActionsLocked(List<AccessibilityNodeInfo> infos) { - if (infos != null) { - for (int i = 0; i < infos.size(); i++) { - replaceActionsOnInfoLocked(infos.get(i)); + try { + mServiceCallback.setFindAccessibilityNodeInfosResult(nodesToReturn, mInteractionId); + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfosResult"); } } - return (infos == null) - ? null : new ArrayList<>(infos); } @GuardedBy("mLock") @@ -257,22 +204,40 @@ public class ActionReplacingCallback extends IAccessibilityInteractionConnection info.setDismissable(false); // We currently only replace actions for the root node if ((info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID) - && mNodeWithReplacementActions != null) { - List<AccessibilityAction> actions = mNodeWithReplacementActions.getActionList(); - if (actions != null) { - for (int j = 0; j < actions.size(); j++) { - info.addAction(actions.get(j)); + && mNodesWithReplacementActions != null) { + // This list should always contain a single node with the root ID + for (int i = 0; i < mNodesWithReplacementActions.size(); i++) { + AccessibilityNodeInfo nodeWithReplacementActions = + mNodesWithReplacementActions.get(i); + if (nodeWithReplacementActions.getSourceNodeId() + == AccessibilityNodeInfo.ROOT_NODE_ID) { + List<AccessibilityAction> actions = nodeWithReplacementActions.getActionList(); + if (actions != null) { + for (int j = 0; j < actions.size(); j++) { + info.addAction(actions.get(j)); + } + // The PIP needs to be able to take accessibility focus + info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS); + info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS); + } + info.setClickable(nodeWithReplacementActions.isClickable()); + info.setFocusable(nodeWithReplacementActions.isFocusable()); + info.setContextClickable(nodeWithReplacementActions.isContextClickable()); + info.setScrollable(nodeWithReplacementActions.isScrollable()); + info.setLongClickable(nodeWithReplacementActions.isLongClickable()); + info.setDismissable(nodeWithReplacementActions.isDismissable()); } - // The PIP needs to be able to take accessibility focus - info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS); - info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS); } - info.setClickable(mNodeWithReplacementActions.isClickable()); - info.setFocusable(mNodeWithReplacementActions.isFocusable()); - info.setContextClickable(mNodeWithReplacementActions.isContextClickable()); - info.setScrollable(mNodeWithReplacementActions.isScrollable()); - info.setLongClickable(mNodeWithReplacementActions.isLongClickable()); - info.setDismissable(mNodeWithReplacementActions.isDismissable()); } } + + @GuardedBy("mLock") + private void recycleReplaceActionNodesLocked() { + if (mNodesWithReplacementActions == null) return; + for (int i = mNodesWithReplacementActions.size() - 1; i >= 0; i--) { + AccessibilityNodeInfo nodeWithReplacementAction = mNodesWithReplacementActions.get(i); + nodeWithReplacementAction.recycle(); + } + mNodesWithReplacementActions = null; + } } diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 342208c8a32b..c2957780c9d7 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -69,7 +69,6 @@ public abstract class PackageManagerInternal { PACKAGE_BROWSER, PACKAGE_SYSTEM_TEXT_CLASSIFIER, PACKAGE_PERMISSION_CONTROLLER, - PACKAGE_WELLBEING, PACKAGE_DOCUMENTER, PACKAGE_CONFIGURATOR, PACKAGE_INCIDENT_REPORT_APPROVER, diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index ad2f52401e93..f73c9a262074 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -314,8 +314,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { /** Gets the subId indicated by the given {@link WifiInfo}. */ public int getSubIdForWifiInfo(@NonNull WifiInfo wifiInfo) { - // TODO(b/178501049): use the subId indicated by WifiInfo#getSubscriptionId - return SubscriptionManager.INVALID_SUBSCRIPTION_ID; + return wifiInfo.getSubscriptionId(); } /** Creates a new LocationPermissionChecker for the provided Context. */ diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9e5d7e4c3325..28503b6052d2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -16652,7 +16652,7 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException("Calling uid " + callingUid + " cannot set locusId" + "for package " + activity.getPackageName()); } - + mActivityTaskManager.setLocusId(locusId, appToken); if (mUsageStatsService != null) { mUsageStatsService.reportLocusUpdate(activity, userId, locusId, appToken); } diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index fc28bfbea710..e2086b01ec13 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -194,6 +194,11 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { final WifiManager wm = mInjector.getSystemService(WifiManager.class); final TelephonyManager tm = mInjector.getSystemService(TelephonyManager.class); final PowerStatsInternal psi = mInjector.getLocalService(PowerStatsInternal.class); + final int voltageMv; + synchronized (mStats) { + voltageMv = mStats.getBatteryVoltageMvLocked(); + } + synchronized (mWorkerLock) { mWifiManager = wm; mTelephony = tm; @@ -212,7 +217,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { // According to spec, initialEcrs will include 0s for consumers that haven't // used any energy yet, as long as they are supported; however, // attributed uid energies will be absent if their energy is 0. - mMeasuredEnergySnapshot.updateAndGetDelta(initialEcrs); + mMeasuredEnergySnapshot.updateAndGetDelta(initialEcrs, voltageMv); } catch (TimeoutException | InterruptedException e) { Slog.w(TAG, "timeout or interrupt reading initial getEnergyConsumedAsync: " + e); @@ -584,10 +589,15 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { Slog.w(TAG, "exception reading modem stats: " + e.getCause()); } - final MeasuredEnergySnapshot.MeasuredEnergyDeltaData measuredEnergyDeltas; + final MeasuredEnergySnapshot.MeasuredEnergyDeltaData measuredEnergyDelta; if (mMeasuredEnergySnapshot == null || futureECRs == null) { - measuredEnergyDeltas = null; + measuredEnergyDelta = null; } else { + final int voltageMv; + synchronized (mStats) { + voltageMv = mStats.getBatteryVoltageMvLocked(); + } + EnergyConsumerResult[] ecrs; try { ecrs = futureECRs.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); @@ -599,7 +609,8 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { Slog.wtf(TAG, "exception reading getEnergyConsumedAsync: " + e.getCause()); ecrs = null; } - measuredEnergyDeltas = mMeasuredEnergySnapshot.updateAndGetDelta(ecrs); + + measuredEnergyDelta = mMeasuredEnergySnapshot.updateAndGetDelta(ecrs, voltageMv); } final long elapsedRealtime = SystemClock.elapsedRealtime(); @@ -620,7 +631,14 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { onBattery = mStats.isOnBatteryLocked(); onBatteryScreenOff = mStats.isOnBatteryScreenOffLocked(); } - mStats.updateCpuTimeLocked(onBattery, onBatteryScreenOff); + + final long[] cpuClusterChargeUC; + if (measuredEnergyDelta == null) { + cpuClusterChargeUC = null; + } else { + cpuClusterChargeUC = measuredEnergyDelta.cpuClusterChargeUC; + } + mStats.updateCpuTimeLocked(onBattery, onBatteryScreenOff, cpuClusterChargeUC); } if (updateFlags == UPDATE_ALL) { @@ -633,20 +651,22 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } // Inform mStats about each applicable measured energy. - if (measuredEnergyDeltas != null) { - final long displayEnergy = measuredEnergyDeltas.displayEnergyUJ; - if (displayEnergy != MeasuredEnergySnapshot.UNAVAILABLE) { + if (measuredEnergyDelta != null) { + final long displayChargeUC = measuredEnergyDelta.displayChargeUC; + if (displayChargeUC != MeasuredEnergySnapshot.UNAVAILABLE) { // If updating, pass in what BatteryExternalStatsWorker thinks screenState is. - mStats.updateDisplayEnergyLocked(displayEnergy, screenState, elapsedRealtime); + mStats.updateDisplayMeasuredEnergyStatsLocked(displayChargeUC, screenState, + elapsedRealtime); } } // Inform mStats about each applicable custom energy bucket. - if (measuredEnergyDeltas != null && measuredEnergyDeltas.otherTotalEnergyUJ != null) { + if (measuredEnergyDelta != null + && measuredEnergyDelta.otherTotalChargeUC != null) { // Iterate over the custom (EnergyConsumerType.OTHER) ordinals. - for (int ord = 0; ord < measuredEnergyDeltas.otherTotalEnergyUJ.length; ord++) { - long totalEnergy = measuredEnergyDeltas.otherTotalEnergyUJ[ord]; - SparseLongArray uidEnergies = measuredEnergyDeltas.otherUidEnergiesUJ[ord]; - mStats.updateCustomMeasuredEnergyDataLocked(ord, totalEnergy, uidEnergies); + for (int ord = 0; ord < measuredEnergyDelta.otherTotalChargeUC.length; ord++) { + long totalEnergy = measuredEnergyDelta.otherTotalChargeUC[ord]; + SparseLongArray uidEnergies = measuredEnergyDelta.otherUidChargesUC[ord]; + mStats.updateCustomMeasuredEnergyStatsLocked(ord, totalEnergy, uidEnergies); } } @@ -664,7 +684,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (wifiInfo != null) { if (wifiInfo.isValid()) { - // TODO: wifiEnergyDelta = measuredEnergyDeltas.consumerTypeEnergyUJ + // TODO: wifiEnergyDelta = measuredEnergyDelta.consumerTypeEnergyUJ // .get(EnergyConsumerType.WIFI, MeasuredEnergySnapshot.UNAVAILABLE) mStats.updateWifiState(extractDeltaLocked(wifiInfo) /*, TODO: wifiEnergyDelta */, elapsedRealtime, uptime); @@ -785,7 +805,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { /** * Map the {@link EnergyConsumerType}s in the given energyArray to - * their corresponding {@link MeasuredEnergyStats.StandardEnergyBucket}s. + * their corresponding {@link MeasuredEnergyStats.StandardPowerBucket}s. * Does not include custom energy buckets (which are always, by definition, supported). * * @return array with true for index i if standard energy bucket i is supported. @@ -795,15 +815,18 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (idToConsumer == null) { return null; } - final boolean[] buckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_ENERGY_BUCKETS]; + final boolean[] buckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; final int size = idToConsumer.size(); for (int idx = 0; idx < size; idx++) { final EnergyConsumer consumer = idToConsumer.valueAt(idx); switch (consumer.type) { case EnergyConsumerType.DISPLAY: - buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON] = true; - buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE] = true; - buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_OTHER] = true; + buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON] = true; + buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE] = true; + buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_OTHER] = true; + break; + case EnergyConsumerType.CPU_CLUSTER: + buckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true; break; } } diff --git a/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java index 9e0aa32a0b9e..9b2ca136bdfb 100644 --- a/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java +++ b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java @@ -25,6 +25,7 @@ import android.hardware.power.stats.EnergyConsumerResult; import android.hardware.power.stats.EnergyConsumerType; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseIntArray; import android.util.SparseLongArray; import com.android.internal.annotations.VisibleForTesting; @@ -38,11 +39,16 @@ import java.io.PrintWriter; public class MeasuredEnergySnapshot { private static final String TAG = "MeasuredEnergySnapshot"; + private static final int MILLIVOLTS_PER_VOLT = 1000; + public static final long UNAVAILABLE = -1L; /** Map of {@link EnergyConsumer#id} to its corresponding {@link EnergyConsumer}. */ private final SparseArray<EnergyConsumer> mEnergyConsumers; + /** Number of ordinals for {@link EnergyConsumerType#CPU_CLUSTER}. */ + private final int mNumCpuClusterOrdinals; + /** Number of ordinals for {@link EnergyConsumerType#OTHER}. */ private final int mNumOtherOrdinals; @@ -59,6 +65,14 @@ public class MeasuredEnergySnapshot { private final SparseLongArray mMeasuredEnergySnapshots; /** + * Voltage snapshots, mapping {@link EnergyConsumer#id} to voltage (mV) from the last time + * each {@link EnergyConsumer} was updated. + * + * see {@link mMeasuredEnergySnapshots}. + */ + private final SparseIntArray mVoltageSnapshots; + + /** * Energy snapshots <b>per uid</b> from the last time each {@link EnergyConsumer} of type * {@link EnergyConsumerType#OTHER} was updated. * It maps each OTHER {@link EnergyConsumer#id} to a SparseLongArray, which itself maps each @@ -77,8 +91,11 @@ public class MeasuredEnergySnapshot { MeasuredEnergySnapshot(@NonNull SparseArray<EnergyConsumer> idToConsumerMap) { mEnergyConsumers = idToConsumerMap; mMeasuredEnergySnapshots = new SparseLongArray(mEnergyConsumers.size()); + mVoltageSnapshots = new SparseIntArray(mEnergyConsumers.size()); - mNumOtherOrdinals = calculateNumOtherOrdinals(idToConsumerMap); + mNumCpuClusterOrdinals = calculateNumOrdinals(EnergyConsumerType.CPU_CLUSTER, + idToConsumerMap); + mNumOtherOrdinals = calculateNumOrdinals(EnergyConsumerType.OTHER, idToConsumerMap); mAttributionSnapshots = new SparseArray<>(mNumOtherOrdinals); } @@ -90,16 +107,19 @@ public class MeasuredEnergySnapshot { return mNumOtherOrdinals; } - /** Class for returning measured energy delta data. */ + /** Class for returning the relevant data calculated from the measured energy delta */ static class MeasuredEnergyDeltaData { - /** The energyUJ for {@link EnergyConsumerType#DISPLAY}. */ - public long displayEnergyUJ = UNAVAILABLE; + /** The chargeUC for {@link EnergyConsumerType#DISPLAY}. */ + public long displayChargeUC = UNAVAILABLE; + + /** The chargeUC for {@link EnergyConsumerType#CPU_CLUSTER}s. */ + public long[] cpuClusterChargeUC = null; - /** Map of {@link EnergyConsumerType#OTHER} ordinals to their total energyUJ. */ - public @Nullable long[] otherTotalEnergyUJ = null; + /** Map of {@link EnergyConsumerType#OTHER} ordinals to their total chargeUC. */ + public @Nullable long[] otherTotalChargeUC = null; - /** Map of {@link EnergyConsumerType#OTHER} ordinals to their {uid->energyUJ} maps. */ - public @Nullable SparseLongArray[] otherUidEnergiesUJ = null; + /** Map of {@link EnergyConsumerType#OTHER} ordinals to their {uid->chargeUC} maps. */ + public @Nullable SparseLongArray[] otherUidChargesUC = null; } /** @@ -108,19 +128,28 @@ public class MeasuredEnergySnapshot { * * @param ecrs EnergyConsumerResults for some (possibly not all) {@link EnergyConsumer}s. * Consumers that are not present are ignored (they are *not* treated as 0). + * @param voltageMV current voltage. * * @return a MeasuredEnergyDeltaData, containing maps from the updated consumers to - * their corresponding energy deltas. + * their corresponding charge deltas. * Fields with no interesting data (consumers not present in ecrs or with no energy * difference) will generally be left as their default values. - * otherTotalEnergyUJ and otherUidEnergiesUJ are always either both null or both of + * otherTotalChargeUC and otherUidChargesUC are always either both null or both of * length {@link #getNumOtherOrdinals()}. * Returns null, if ecrs is null or empty. */ - public @Nullable MeasuredEnergyDeltaData updateAndGetDelta(EnergyConsumerResult[] ecrs) { + public @Nullable MeasuredEnergyDeltaData updateAndGetDelta(EnergyConsumerResult[] ecrs, + int voltageMV) { if (ecrs == null || ecrs.length == 0) { return null; } + if (voltageMV <= 0) { + Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMV + + " mV) when taking measured energy snapshot"); + // TODO (b/181685156): consider adding the nominal voltage to power profile and + // falling back to it if measured voltage is unavailable. + return null; + } final MeasuredEnergyDeltaData output = new MeasuredEnergyDeltaData(); for (final EnergyConsumerResult ecr : ecrs) { @@ -138,12 +167,15 @@ public class MeasuredEnergySnapshot { final int type = consumer.type; final int ordinal = consumer.ordinal; - // Look up, and update, the old energy information about this consumer. + // Look up, and update, the old energy and voltage information about this consumer. final long oldEnergyUJ = mMeasuredEnergySnapshots.get(consumerId, UNAVAILABLE); + final int oldVoltageMV = mVoltageSnapshots.get(consumerId); mMeasuredEnergySnapshots.put(consumerId, newEnergyUJ); - final SparseLongArray otherUidEnergies - = updateAndGetDeltaForTypeOther(consumer, newAttributions); + mVoltageSnapshots.put(consumerId, voltageMV); + final int avgVoltageMV = (oldVoltageMV + voltageMV + 1) / 2; + final SparseLongArray otherUidCharges = + updateAndGetDeltaForTypeOther(consumer, newAttributions, avgVoltageMV); // Everything is fully done being updated. We now calculate the delta for returning. // NB: Since sum(attribution.energyUWs)<=energyUWs we assume that if deltaEnergy==0 @@ -152,24 +184,36 @@ public class MeasuredEnergySnapshot { if (oldEnergyUJ < 0) continue; // Generally happens only on initialization. if (newEnergyUJ == oldEnergyUJ) continue; + final long deltaUJ = newEnergyUJ - oldEnergyUJ; - if (deltaUJ < 0) { - Slog.e(TAG, "EnergyConsumer " + consumer.name + ": new energy (" + newEnergyUJ - + ") < old energy (" + oldEnergyUJ + "). Skipping. "); + if (deltaUJ < 0 || oldVoltageMV <= 0) { + Slog.e(TAG, "Bad data! EnergyConsumer " + consumer.name + + ": new energy (" + newEnergyUJ + ") < old energy (" + oldEnergyUJ + + "), new voltage (" + voltageMV + "), old voltage (" + oldVoltageMV + + "). Skipping. "); continue; } + final long deltaChargeUC = calculateChargeConsumedUC(deltaUJ, avgVoltageMV); switch (type) { case EnergyConsumerType.DISPLAY: - output.displayEnergyUJ = deltaUJ; + output.displayChargeUC = deltaChargeUC; break; + + case EnergyConsumerType.CPU_CLUSTER: + if (output.cpuClusterChargeUC == null) { + output.cpuClusterChargeUC = new long[mNumCpuClusterOrdinals]; + } + output.cpuClusterChargeUC[ordinal] = deltaChargeUC; + break; + case EnergyConsumerType.OTHER: - if (output.otherTotalEnergyUJ == null) { - output.otherTotalEnergyUJ = new long[getNumOtherOrdinals()]; - output.otherUidEnergiesUJ = new SparseLongArray[getNumOtherOrdinals()]; + if (output.otherTotalChargeUC == null) { + output.otherTotalChargeUC = new long[getNumOtherOrdinals()]; + output.otherUidChargesUC = new SparseLongArray[getNumOtherOrdinals()]; } - output.otherTotalEnergyUJ[ordinal] = deltaUJ; - output.otherUidEnergiesUJ[ordinal] = otherUidEnergies; + output.otherTotalChargeUC[ordinal] = deltaChargeUC; + output.otherUidChargesUC[ordinal] = otherUidCharges; break; default: Slog.w(TAG, "Ignoring consumer " + consumer.name + " of unknown type " + type); @@ -182,19 +226,21 @@ public class MeasuredEnergySnapshot { /** * For a consumer of type {@link EnergyConsumerType#OTHER}, updates * {@link #mAttributionSnapshots} with freshly measured energies (per uid) and returns the - * difference (delta) between the previously stored values and the passed-in values. + * charge consumed (in microcouloumbs) between the previously stored values and the passed-in + * values. * * @param consumerInfo a consumer of type {@link EnergyConsumerType#OTHER}. * @param newAttributions Record of uids and their new energyUJ values. * Any uid not present is treated as having energy 0. * If null or empty, all uids are treated as having energy 0. - * @return A map (in the sense of {@link MeasuredEnergyDeltaData#otherUidEnergiesUJ} for this - * consumer) of uid -> energyDelta, with all uids that have a non-zero energyDelta. + * @param avgVoltageMV The average voltage since the last snapshot. + * @return A map (in the sense of {@link MeasuredEnergyDeltaData#otherUidChargesUC} for this + * consumer) of uid -> chargeDelta, with all uids that have a non-zero chargeDelta. * Returns null if no delta available to calculate. */ private @Nullable SparseLongArray updateAndGetDeltaForTypeOther( @NonNull EnergyConsumer consumerInfo, - @Nullable EnergyConsumerAttribution[] newAttributions) { + @Nullable EnergyConsumerAttribution[] newAttributions, int avgVoltageMV) { if (consumerInfo.type != EnergyConsumerType.OTHER) { return null; @@ -217,8 +263,8 @@ public class MeasuredEnergySnapshot { return null; } - // Map uid -> energyDelta. No initial capacity since many deltas might be 0. - final SparseLongArray uidEnergyDeltas = new SparseLongArray(); + // Map uid -> chargeDelta. No initial capacity since many deltas might be 0. + final SparseLongArray uidChargeDeltas = new SparseLongArray(); for (EnergyConsumerAttribution newAttribution : newAttributions) { final int uid = newAttribution.uid; @@ -231,14 +277,17 @@ public class MeasuredEnergySnapshot { if (oldEnergyUJ < 0) continue; if (newEnergyUJ == oldEnergyUJ) continue; final long deltaUJ = newEnergyUJ - oldEnergyUJ; - if (deltaUJ < 0) { + if (deltaUJ < 0 || avgVoltageMV <= 0) { Slog.e(TAG, "EnergyConsumer " + consumerInfo.name + ": new energy (" + newEnergyUJ - + ") but old energy (" + oldEnergyUJ + "). Skipping. "); + + ") but old energy (" + oldEnergyUJ + "). Average voltage (" + avgVoltageMV + + ")Skipping. "); continue; } - uidEnergyDeltas.put(uid, deltaUJ); + + final long deltaChargeUC = calculateChargeConsumedUC(deltaUJ, avgVoltageMV); + uidChargeDeltas.put(uid, deltaChargeUC); } - return uidEnergyDeltas; + return uidChargeDeltas; } /** Dump debug data. */ @@ -255,22 +304,33 @@ public class MeasuredEnergySnapshot { for (int i = 0; i < mMeasuredEnergySnapshots.size(); i++) { final int id = mMeasuredEnergySnapshots.keyAt(i); final long energyUJ = mMeasuredEnergySnapshots.valueAt(i); - pw.println(String.format(" Consumer %d has energy %d uJ}", id, energyUJ)); + final long voltageMV = mVoltageSnapshots.valueAt(i); + pw.println(String.format(" Consumer %d has energy %d uJ at %d mV", id, energyUJ, + voltageMV)); } pw.println("List of the " + mNumOtherOrdinals + " OTHER EnergyConsumers:"); pw.println(" " + mAttributionSnapshots); pw.println(); } - /** Determines the number of ordinals for {@link EnergyConsumerType#OTHER}. */ - private static int calculateNumOtherOrdinals(SparseArray<EnergyConsumer> idToConsumer) { + /** Determines the number of ordinals for a given {@link EnergyConsumerType}. */ + private static int calculateNumOrdinals(@EnergyConsumerType int type, + SparseArray<EnergyConsumer> idToConsumer) { if (idToConsumer == null) return 0; - int numOtherOrdinals = 0; + int numOrdinals = 0; final int size = idToConsumer.size(); for (int idx = 0; idx < size; idx++) { final EnergyConsumer consumer = idToConsumer.valueAt(idx); - if (consumer.type == EnergyConsumerType.OTHER) numOtherOrdinals++; + if (consumer.type == type) numOrdinals++; } - return numOtherOrdinals; + return numOrdinals; + } + + /** Calculate charge consumption (in microcouloumbs) from a given energy and voltage */ + private long calculateChargeConsumedUC(long deltaEnergyUJ, int avgVoltageMV) { + // To overflow, a 3.7V 10000mAh battery would need to completely drain 69244 times + // since the last snapshot. Round up to the nearest whole long. + return (deltaEnergyUJ * MILLIVOLTS_PER_VOLT + (avgVoltageMV + 1) / 2) / avgVoltageMV; } + } diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index 968cf5f1df91..2c0a5891c4b9 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -314,17 +314,8 @@ public final class AppHibernationService extends SystemService { private void unhibernatePackageForUser(@NonNull String packageName, int userId, UserLevelState pkgState) { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage"); - final long caller = Binder.clearCallingIdentity(); - try { - mIPackageManager.setPackageStoppedState(packageName, false, userId); - pkgState.hibernated = false; - } catch (RemoteException e) { - throw new IllegalStateException( - "Failed to unhibernate due to manager not being available", e); - } finally { - Binder.restoreCallingIdentity(caller); - Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); - } + pkgState.hibernated = false; + Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } /** diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 088249e81171..7dfecd56eaf5 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -179,8 +179,7 @@ public class ClipboardService extends SystemService { private final ContentCaptureManagerInternal mContentCaptureInternal; private final AutofillManagerInternal mAutofillInternal; private final IBinder mPermissionOwner; - private HostClipboardMonitor mHostClipboardMonitor = null; - private Thread mHostMonitorThread = null; + private final HostClipboardMonitor mHostClipboardMonitor; @GuardedBy("mLock") private final SparseArray<PerUserClipboard> mClipboards = new SparseArray<>(); @@ -217,13 +216,15 @@ public class ClipboardService extends SystemService { new String[]{"text/plain"}, new ClipData.Item(contents)); synchronized (mLock) { - setPrimaryClipInternal(getClipboard(0), clip, + setPrimaryClipInternalLocked(getClipboardLocked(0), clip, android.os.Process.SYSTEM_UID, null); } } }); - mHostMonitorThread = new Thread(mHostClipboardMonitor); - mHostMonitorThread.start(); + Thread hostMonitorThread = new Thread(mHostClipboardMonitor); + hostMonitorThread.start(); + } else { + mHostClipboardMonitor = null; } updateConfig(); @@ -378,47 +379,60 @@ public class ClipboardService extends SystemService { @Override public void setPrimaryClip(ClipData clip, String callingPackage, @UserIdInt int userId) { - synchronized (this) { - if (clip == null || clip.getItemCount() <= 0) { - throw new IllegalArgumentException("No items"); - } - final int intendingUid = getIntendingUid(callingPackage, userId); - final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, - intendingUid, intendingUserId)) { - return; - } - checkDataOwnerLocked(clip, intendingUid); - setPrimaryClipInternal(clip, intendingUid, callingPackage); + checkAndSetPrimaryClip(clip, callingPackage, userId, callingPackage); + } + + @Override + public void setPrimaryClipAsPackage( + ClipData clip, String callingPackage, @UserIdInt int userId, String sourcePackage) { + getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE, + "Requires SET_CLIP_SOURCE permission"); + checkAndSetPrimaryClip(clip, callingPackage, userId, sourcePackage); + } + + private void checkAndSetPrimaryClip( + ClipData clip, String callingPackage, @UserIdInt int userId, String sourcePackage) { + if (clip == null || clip.getItemCount() <= 0) { + throw new IllegalArgumentException("No items"); + } + final int intendingUid = getIntendingUid(callingPackage, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, + intendingUid, intendingUserId)) { + return; + } + checkDataOwner(clip, intendingUid); + synchronized (mLock) { + setPrimaryClipInternalLocked(clip, intendingUid, sourcePackage); } } @Override public void clearPrimaryClip(String callingPackage, @UserIdInt int userId) { - synchronized (this) { - final int intendingUid = getIntendingUid(callingPackage, userId); - final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, - intendingUid, intendingUserId)) { - return; - } - setPrimaryClipInternal(null, intendingUid, callingPackage); + final int intendingUid = getIntendingUid(callingPackage, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage, + intendingUid, intendingUserId)) { + return; + } + synchronized (mLock) { + setPrimaryClipInternalLocked(null, intendingUid, callingPackage); } } @Override public ClipData getPrimaryClip(String pkg, @UserIdInt int userId) { - synchronized (this) { - final int intendingUid = getIntendingUid(pkg, userId); - final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg, - intendingUid, intendingUserId) - || isDeviceLocked(intendingUserId)) { - return null; - } + final int intendingUid = getIntendingUid(pkg, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg, + intendingUid, intendingUserId) + || isDeviceLocked(intendingUserId)) { + return null; + } + synchronized (mLock) { addActiveOwnerLocked(intendingUid, pkg); - PerUserClipboard clipboard = getClipboard(intendingUserId); - maybeNotify(pkg, intendingUid, intendingUserId, clipboard); + PerUserClipboard clipboard = getClipboardLocked(intendingUserId); + maybeNotifyLocked(pkg, intendingUid, intendingUserId, clipboard); return clipboard.primaryClip; } } @@ -426,15 +440,15 @@ public class ClipboardService extends SystemService { @Override public ClipDescription getPrimaryClipDescription(String callingPackage, @UserIdInt int userId) { - synchronized (this) { - final int intendingUid = getIntendingUid(callingPackage, userId); - final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - intendingUid, intendingUserId, false) - || isDeviceLocked(intendingUserId)) { - return null; - } - PerUserClipboard clipboard = getClipboard(intendingUserId); + final int intendingUid = getIntendingUid(callingPackage, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, + intendingUid, intendingUserId, false) + || isDeviceLocked(intendingUserId)) { + return null; + } + synchronized (mLock) { + PerUserClipboard clipboard = getClipboardLocked(intendingUserId); return clipboard.primaryClip != null ? clipboard.primaryClip.getDescription() : null; } @@ -442,25 +456,25 @@ public class ClipboardService extends SystemService { @Override public boolean hasPrimaryClip(String callingPackage, @UserIdInt int userId) { - synchronized (this) { - final int intendingUid = getIntendingUid(callingPackage, userId); - final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - intendingUid, intendingUserId, false) - || isDeviceLocked(intendingUserId)) { - return false; - } - return getClipboard(intendingUserId).primaryClip != null; + final int intendingUid = getIntendingUid(callingPackage, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, + intendingUid, intendingUserId, false) + || isDeviceLocked(intendingUserId)) { + return false; + } + synchronized (mLock) { + return getClipboardLocked(intendingUserId).primaryClip != null; } } @Override public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener, String callingPackage, @UserIdInt int userId) { - synchronized (this) { - final int intendingUid = getIntendingUid(callingPackage, userId); - final int intendingUserId = UserHandle.getUserId(intendingUid); - getClipboard(intendingUserId).primaryClipListeners.register(listener, + final int intendingUid = getIntendingUid(callingPackage, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + synchronized (mLock) { + getClipboardLocked(intendingUserId).primaryClipListeners.register(listener, new ListenerInfo(intendingUid, callingPackage)); } } @@ -468,23 +482,23 @@ public class ClipboardService extends SystemService { @Override public void removePrimaryClipChangedListener(IOnPrimaryClipChangedListener listener, String callingPackage, @UserIdInt int userId) { - synchronized (this) { - final int intendingUserId = getIntendingUserId(callingPackage, userId); - getClipboard(intendingUserId).primaryClipListeners.unregister(listener); + final int intendingUserId = getIntendingUserId(callingPackage, userId); + synchronized (mLock) { + getClipboardLocked(intendingUserId).primaryClipListeners.unregister(listener); } } @Override public boolean hasClipboardText(String callingPackage, int userId) { - synchronized (this) { - final int intendingUid = getIntendingUid(callingPackage, userId); - final int intendingUserId = UserHandle.getUserId(intendingUid); - if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - intendingUid, intendingUserId, false) - || isDeviceLocked(intendingUserId)) { - return false; - } - PerUserClipboard clipboard = getClipboard(intendingUserId); + final int intendingUid = getIntendingUid(callingPackage, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, + intendingUid, intendingUserId, false) + || isDeviceLocked(intendingUserId)) { + return false; + } + synchronized (mLock) { + PerUserClipboard clipboard = getClipboardLocked(intendingUserId); if (clipboard.primaryClip != null) { CharSequence text = clipboard.primaryClip.getItemAt(0).getText(); return text != null && text.length() > 0; @@ -492,17 +506,36 @@ public class ClipboardService extends SystemService { return false; } } - }; - private PerUserClipboard getClipboard(@UserIdInt int userId) { - synchronized (mLock) { - PerUserClipboard puc = mClipboards.get(userId); - if (puc == null) { - puc = new PerUserClipboard(userId); - mClipboards.put(userId, puc); + @Override + public String getPrimaryClipSource(String callingPackage, int userId) { + getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE, + "Requires SET_CLIP_SOURCE permission"); + final int intendingUid = getIntendingUid(callingPackage, userId); + final int intendingUserId = UserHandle.getUserId(intendingUid); + if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, + intendingUid, intendingUserId, false) + || isDeviceLocked(intendingUserId)) { + return null; } - return puc; + synchronized (mLock) { + PerUserClipboard clipboard = getClipboardLocked(intendingUserId); + if (clipboard.primaryClip != null) { + return clipboard.mPrimaryClipPackage; + } + return null; + } + } + }; + + @GuardedBy("mLock") + private PerUserClipboard getClipboardLocked(@UserIdInt int userId) { + PerUserClipboard puc = mClipboards.get(userId); + if (puc == null) { + puc = new PerUserClipboard(userId); + mClipboards.put(userId, puc); } + return puc; } List<UserInfo> getRelatedProfiles(@UserIdInt int userId) { @@ -533,10 +566,13 @@ public class ClipboardService extends SystemService { } void setPrimaryClipInternal(@Nullable ClipData clip, int uid) { - setPrimaryClipInternal(clip, uid, null); + synchronized (mLock) { + setPrimaryClipInternalLocked(clip, uid, null); + } } - private void setPrimaryClipInternal( + @GuardedBy("mLock") + private void setPrimaryClipInternalLocked( @Nullable ClipData clip, int uid, @Nullable String sourcePackage) { // Push clipboard to host, if any if (mHostClipboardMonitor != null) { @@ -553,7 +589,7 @@ public class ClipboardService extends SystemService { // Update this user final int userId = UserHandle.getUserId(uid); - setPrimaryClipInternal(getClipboard(userId), clip, uid, sourcePackage); + setPrimaryClipInternalLocked(getClipboardLocked(userId), clip, uid, sourcePackage); // Update related users List<UserInfo> related = getRelatedProfiles(userId); @@ -587,8 +623,8 @@ public class ClipboardService extends SystemService { final boolean canCopyIntoProfile = !hasRestriction( UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id); if (canCopyIntoProfile) { - setPrimaryClipInternal( - getClipboard(id), clip, uid, sourcePackage); + setPrimaryClipInternalLocked( + getClipboardLocked(id), clip, uid, sourcePackage); } } } @@ -598,10 +634,13 @@ public class ClipboardService extends SystemService { void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip, int uid) { - setPrimaryClipInternal(clipboard, clip, uid, null); + synchronized ("mLock") { + setPrimaryClipInternalLocked(clipboard, clip, uid, null); + } } - private void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip, + @GuardedBy("mLock") + private void setPrimaryClipInternalLocked(PerUserClipboard clipboard, @Nullable ClipData clip, int uid, @Nullable String sourcePackage) { revokeUris(clipboard); clipboard.activePermissionOwners.clear(); @@ -657,7 +696,7 @@ public class ClipboardService extends SystemService { } } - private final void checkUriOwnerLocked(Uri uri, int sourceUid) { + private void checkUriOwner(Uri uri, int sourceUid) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; final long ident = Binder.clearCallingIdentity(); @@ -672,24 +711,24 @@ public class ClipboardService extends SystemService { } } - private final void checkItemOwnerLocked(ClipData.Item item, int uid) { + private void checkItemOwner(ClipData.Item item, int uid) { if (item.getUri() != null) { - checkUriOwnerLocked(item.getUri(), uid); + checkUriOwner(item.getUri(), uid); } Intent intent = item.getIntent(); if (intent != null && intent.getData() != null) { - checkUriOwnerLocked(intent.getData(), uid); + checkUriOwner(intent.getData(), uid); } } - private final void checkDataOwnerLocked(ClipData data, int uid) { + private void checkDataOwner(ClipData data, int uid) { final int N = data.getItemCount(); for (int i=0; i<N; i++) { - checkItemOwnerLocked(data.getItemAt(i), uid); + checkItemOwner(data.getItemAt(i), uid); } } - private final void grantUriLocked(Uri uri, int sourceUid, String targetPkg, + private void grantUriPermission(Uri uri, int sourceUid, String targetPkg, int targetUserId) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; @@ -707,18 +746,19 @@ public class ClipboardService extends SystemService { } } - private final void grantItemLocked(ClipData.Item item, int sourceUid, String targetPkg, + private void grantItemPermission(ClipData.Item item, int sourceUid, String targetPkg, int targetUserId) { if (item.getUri() != null) { - grantUriLocked(item.getUri(), sourceUid, targetPkg, targetUserId); + grantUriPermission(item.getUri(), sourceUid, targetPkg, targetUserId); } Intent intent = item.getIntent(); if (intent != null && intent.getData() != null) { - grantUriLocked(intent.getData(), sourceUid, targetPkg, targetUserId); + grantUriPermission(intent.getData(), sourceUid, targetPkg, targetUserId); } } - private final void addActiveOwnerLocked(int uid, String pkg) { + @GuardedBy("mLock") + private void addActiveOwnerLocked(int uid, String pkg) { final IPackageManager pm = AppGlobals.getPackageManager(); final int targetUserHandle = UserHandle.getCallingUserId(); final long oldIdentity = Binder.clearCallingIdentity(); @@ -736,18 +776,18 @@ public class ClipboardService extends SystemService { } finally { Binder.restoreCallingIdentity(oldIdentity); } - PerUserClipboard clipboard = getClipboard(UserHandle.getUserId(uid)); + PerUserClipboard clipboard = getClipboardLocked(UserHandle.getUserId(uid)); if (clipboard.primaryClip != null && !clipboard.activePermissionOwners.contains(pkg)) { final int N = clipboard.primaryClip.getItemCount(); for (int i=0; i<N; i++) { - grantItemLocked(clipboard.primaryClip.getItemAt(i), clipboard.primaryClipUid, pkg, - UserHandle.getUserId(uid)); + grantItemPermission(clipboard.primaryClip.getItemAt(i), clipboard.primaryClipUid, + pkg, UserHandle.getUserId(uid)); } clipboard.activePermissionOwners.add(pkg); } } - private final void revokeUriLocked(Uri uri, int sourceUid) { + private void revokeUriPermission(Uri uri, int sourceUid) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; final long ident = Binder.clearCallingIdentity(); @@ -761,23 +801,23 @@ public class ClipboardService extends SystemService { } } - private final void revokeItemLocked(ClipData.Item item, int sourceUid) { + private void revokeItemPermission(ClipData.Item item, int sourceUid) { if (item.getUri() != null) { - revokeUriLocked(item.getUri(), sourceUid); + revokeUriPermission(item.getUri(), sourceUid); } Intent intent = item.getIntent(); if (intent != null && intent.getData() != null) { - revokeUriLocked(intent.getData(), sourceUid); + revokeUriPermission(intent.getData(), sourceUid); } } - private final void revokeUris(PerUserClipboard clipboard) { + private void revokeUris(PerUserClipboard clipboard) { if (clipboard.primaryClip == null) { return; } final int N = clipboard.primaryClip.getItemCount(); for (int i=0; i<N; i++) { - revokeItemLocked(clipboard.primaryClip.getItemAt(i), clipboard.primaryClipUid); + revokeItemPermission(clipboard.primaryClip.getItemAt(i), clipboard.primaryClipUid); } } @@ -867,15 +907,14 @@ public class ClipboardService extends SystemService { * Potentially notifies the user (via a toast) about an app accessing the clipboard. * TODO(b/167676460): STOPSHIP as we don't want this code as-is to launch. Just an experiment. */ - private void maybeNotify(String callingPackage, int uid, @UserIdInt int userId, + @GuardedBy("mLock") + private void maybeNotifyLocked(String callingPackage, int uid, @UserIdInt int userId, PerUserClipboard clipboard) { if (clipboard.primaryClip == null) { return; } - synchronized (mLock) { - if (!mShowAccessNotifications) { - return; - } + if (!mShowAccessNotifications) { + return; } // Don't notify if the app accessing the clipboard is the same as the current owner. if (UserHandle.isSameApp(uid, clipboard.primaryClipUid)) { diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index ae0e001e8417..df870125e253 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -17,6 +17,7 @@ package com.android.server.content; import static android.os.PowerWhitelistManager.REASON_SYNC_MANAGER; +import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; import static com.android.server.content.SyncLogger.logSafe; @@ -1672,6 +1673,7 @@ public class SyncManager { dic.addPowerSaveTempWhitelistApp(Process.SYSTEM_UID, syncOperation.owningPackage, mConstants.getKeyExemptionTempWhitelistDurationInSeconds() * 1000, + TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, UserHandle.getUserId(syncOperation.owningUid), /* sync=*/ false, REASON_SYNC_MANAGER, "sync by top app"); } diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index a0d93656b7f6..d88896c01e4b 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -683,12 +683,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { setDisplayState(Display.STATE_ON); currentState = Display.STATE_ON; } else { - if (oldState == Display.STATE_UNKNOWN) { - // There's no guarantee about what the initial state is - // at startup, so we have to set it if previous was UNKNOWN. - setDisplayState(state); - } - return; + return; // old state and new state is off } } diff --git a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java index 7b646b36124b..e01c37901563 100644 --- a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java +++ b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java @@ -22,11 +22,8 @@ import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.DisplayStatusCallback; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.os.RemoteException; import android.util.Slog; -import java.util.ArrayList; -import java.util.List; /** * Feature action that queries the power status of other device. This action is initiated via @@ -42,7 +39,6 @@ final class DevicePowerStatusAction extends HdmiCecFeatureAction { private static final int STATE_WAITING_FOR_REPORT_POWER_STATUS = 1; private final int mTargetAddress; - private final List<IHdmiControlCallback> mCallbacks = new ArrayList<>(); // Retry the power status query as it might happen when the target device is waking up. In // that case a device may be quite busy and can fail to respond within the 2s timeout. @@ -59,9 +55,8 @@ final class DevicePowerStatusAction extends HdmiCecFeatureAction { private DevicePowerStatusAction(HdmiCecLocalDevice localDevice, int targetAddress, IHdmiControlCallback callback) { - super(localDevice); + super(localDevice, callback); mTargetAddress = targetAddress; - addCallback(callback); } @Override @@ -74,8 +69,7 @@ final class DevicePowerStatusAction extends HdmiCecFeatureAction { && deviceInfo.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0) { int powerStatus = deviceInfo.getDevicePowerStatus(); if (powerStatus != HdmiControlManager.POWER_STATUS_UNKNOWN) { - invokeCallback(powerStatus); - finish(); + finishWithCallback(powerStatus); return true; } } @@ -93,8 +87,7 @@ final class DevicePowerStatusAction extends HdmiCecFeatureAction { // the device is not present or not capable of CEC. if (error == SendMessageResult.NACK) { // Got no response from TV. Report status 'unknown'. - invokeCallback(HdmiControlManager.POWER_STATUS_UNKNOWN); - finish(); + finishWithCallback(HdmiControlManager.POWER_STATUS_UNKNOWN); } }); } @@ -107,8 +100,7 @@ final class DevicePowerStatusAction extends HdmiCecFeatureAction { } if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) { int status = cmd.getParams()[0]; - invokeCallback(status); - finish(); + finishWithCallback(status); return true; } return false; @@ -127,22 +119,7 @@ final class DevicePowerStatusAction extends HdmiCecFeatureAction { } // Got no response from TV. Report status 'unknown'. - invokeCallback(HdmiControlManager.POWER_STATUS_UNKNOWN); - finish(); - } - } - - public void addCallback(IHdmiControlCallback callback) { - mCallbacks.add(callback); - } - - private void invokeCallback(int result) { - try { - for (IHdmiControlCallback callback : mCallbacks) { - callback.onComplete(result); - } - } catch (RemoteException e) { - Slog.e(TAG, "Callback failed:" + e); + finishWithCallback(HdmiControlManager.POWER_STATUS_UNKNOWN); } } } diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java index 983b6b5bceb4..c23e2e691b55 100644 --- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java +++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java @@ -21,7 +21,6 @@ import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiTvClient; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.os.RemoteException; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; @@ -63,7 +62,6 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3; private final HdmiDeviceInfo mTarget; - private final IHdmiControlCallback mCallback; private final HdmiCecMessage mGivePowerStatus; private final boolean mIsCec20; @@ -86,8 +84,7 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { @VisibleForTesting DeviceSelectAction(HdmiCecLocalDeviceTv source, HdmiDeviceInfo target, IHdmiControlCallback callback, boolean isCec20) { - super(source); - mCallback = callback; + super(source, callback); mTarget = target; mGivePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus( getSourceAddress(), getTargetAddress()); @@ -108,7 +105,7 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { if (!mIsCec20 || targetPowerStatus == HdmiControlManager.POWER_STATUS_UNKNOWN) { queryDevicePowerStatus(); } else if (targetPowerStatus == HdmiControlManager.POWER_STATUS_ON) { - invokeCallbackAndFinish(HdmiControlManager.RESULT_SUCCESS); + finishWithCallback(HdmiControlManager.RESULT_SUCCESS); return true; } mState = STATE_WAIT_FOR_REPORT_POWER_STATUS; @@ -117,14 +114,17 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { } private void queryDevicePowerStatus() { - sendCommand(mGivePowerStatus, new SendMessageCallback() { - @Override - public void onSendCompleted(int error) { - if (error != SendMessageResult.SUCCESS) { - invokeCallbackAndFinish(HdmiControlManager.RESULT_COMMUNICATION_FAILED); - } - } - }); + sendCommand( + mGivePowerStatus, + new SendMessageCallback() { + @Override + public void onSendCompleted(int error) { + if (error != SendMessageResult.SUCCESS) { + finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED); + return; + } + } + }); } @Override @@ -189,7 +189,7 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { switch (mState) { case STATE_WAIT_FOR_REPORT_POWER_STATUS: if (tv().isPowerStandbyOrTransient()) { - invokeCallbackAndFinish(HdmiControlManager.RESULT_INCORRECT_MODE); + finishWithCallback(HdmiControlManager.RESULT_INCORRECT_MODE); return; } selectDevice(); @@ -217,7 +217,7 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { if (!mIsCec20) { sendSetStreamPath(); } - invokeCallbackAndFinish(HdmiControlManager.RESULT_SUCCESS); + finishWithCallback(HdmiControlManager.RESULT_SUCCESS); } private void sendSetStreamPath() { @@ -228,15 +228,4 @@ final class DeviceSelectAction extends HdmiCecFeatureAction { sendCommand(HdmiCecMessageBuilder.buildSetStreamPath( getSourceAddress(), mTarget.getPhysicalAddress())); } - - private void invokeCallbackAndFinish(int result) { - if (mCallback != null) { - try { - mCallback.onComplete(result); - } catch (RemoteException e) { - Slog.e(TAG, "Callback failed:" + e); - } - } - finish(); - } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java index 2da698be56be..2e1ff038931d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java @@ -15,9 +15,11 @@ */ package com.android.server.hdmi; +import android.hardware.hdmi.IHdmiControlCallback; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.RemoteException; import android.util.Pair; import android.util.Slog; @@ -25,6 +27,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.hdmi.HdmiControlService.DevicePollingCallback; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -61,7 +64,20 @@ abstract class HdmiCecFeatureAction { private ArrayList<Pair<HdmiCecFeatureAction, Runnable>> mOnFinishedCallbacks; + final List<IHdmiControlCallback> mCallbacks = new ArrayList<>(); + HdmiCecFeatureAction(HdmiCecLocalDevice source) { + this(source, new ArrayList<>()); + } + + HdmiCecFeatureAction(HdmiCecLocalDevice source, IHdmiControlCallback callback) { + this(source, Arrays.asList(callback)); + } + + HdmiCecFeatureAction(HdmiCecLocalDevice source, List<IHdmiControlCallback> callbacks) { + for (IHdmiControlCallback callback : callbacks) { + addCallback(callback); + } mSource = source; mService = mSource.getService(); mActionTimer = createActionTimer(mService.getServiceLooper()); @@ -282,4 +298,26 @@ abstract class HdmiCecFeatureAction { } mOnFinishedCallbacks.add(Pair.create(action, runnable)); } + + protected void finishWithCallback(int returnCode) { + invokeCallback(returnCode); + finish(); + } + + public void addCallback(IHdmiControlCallback callback) { + mCallbacks.add(callback); + } + + private void invokeCallback(int result) { + try { + for (IHdmiControlCallback callback : mCallbacks) { + if (callback == null) { + continue; + } + callback.onComplete(result); + } + } catch (RemoteException e) { + Slog.e(TAG, "Callback failed:" + e); + } + } } diff --git a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java index ea6e61582ea0..02b09b15b464 100644 --- a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java +++ b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java @@ -18,11 +18,8 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; import android.hardware.hdmi.IHdmiControlCallback; -import android.os.RemoteException; import android.util.Slog; -import java.util.ArrayList; -import java.util.List; /** * Feature action that performs one touch play against TV/Display device. This action is initiated @@ -50,7 +47,6 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { private static final int LOOP_COUNTER_MAX = 10; private final int mTargetAddress; - private final List<IHdmiControlCallback> mCallbacks = new ArrayList<>(); private int mPowerStatusCounter = 0; @@ -69,9 +65,8 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { private OneTouchPlayAction(HdmiCecLocalDevice localDevice, int targetAddress, IHdmiControlCallback callback) { - super(localDevice); + super(localDevice, callback); mTargetAddress = targetAddress; - addCallback(callback); } @Override @@ -121,8 +116,7 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { int status = cmd.getParams()[0]; if (status == HdmiControlManager.POWER_STATUS_ON) { broadcastActiveSource(); - invokeCallback(HdmiControlManager.RESULT_SUCCESS); - finish(); + finishWithCallback(HdmiControlManager.RESULT_SUCCESS); } return true; } @@ -140,26 +134,11 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { addTimer(mState, HdmiConfig.TIMEOUT_MS); } else { // Couldn't wake up the TV for whatever reason. Report failure. - invokeCallback(HdmiControlManager.RESULT_TIMEOUT); - finish(); + finishWithCallback(HdmiControlManager.RESULT_TIMEOUT); } } } - public void addCallback(IHdmiControlCallback callback) { - mCallbacks.add(callback); - } - - private void invokeCallback(int result) { - try { - for (IHdmiControlCallback callback : mCallbacks) { - callback.onComplete(result); - } - } catch (RemoteException e) { - Slog.e(TAG, "Callback failed:" + e); - } - } - private boolean shouldTurnOnConnectedAudioSystem() { HdmiControlService service = mSource.mService; if (service.isAudioSystemDevice()) { @@ -170,4 +149,5 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE); return sendStandbyOnSleep.equals(HdmiControlManager.POWER_CONTROL_MODE_BROADCAST); } + } diff --git a/services/core/java/com/android/server/hdmi/RoutingControlAction.java b/services/core/java/com/android/server/hdmi/RoutingControlAction.java index 6c147ed5e6d6..b9404e407b88 100644 --- a/services/core/java/com/android/server/hdmi/RoutingControlAction.java +++ b/services/core/java/com/android/server/hdmi/RoutingControlAction.java @@ -16,11 +16,9 @@ package com.android.server.hdmi; -import android.annotation.Nullable; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; -import android.os.RemoteException; import android.util.Slog; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; @@ -66,15 +64,12 @@ final class RoutingControlAction extends HdmiCecFeatureAction { // <Inactive Source> command. private final boolean mNotifyInputChange; - @Nullable private final IHdmiControlCallback mCallback; - // The latest routing path. Updated by each <Routing Information> from CEC switches. private int mCurrentRoutingPath; RoutingControlAction(HdmiCecLocalDevice localDevice, int path, boolean queryDevicePowerStatus, IHdmiControlCallback callback) { - super(localDevice); - mCallback = callback; + super(localDevice, callback); mCurrentRoutingPath = path; mQueryDevicePowerStatus = queryDevicePowerStatus; // Callback is non-null when routing control action is brought up by binder API. Use @@ -147,11 +142,6 @@ final class RoutingControlAction extends HdmiCecFeatureAction { mCurrentRoutingPath)); } - private void finishWithCallback(int result) { - invokeCallback(result); - finish(); - } - @Override public void handleTimerEvent(int timeoutState) { if (mState != timeoutState || mState == STATE_NONE) { @@ -202,15 +192,4 @@ final class RoutingControlAction extends HdmiCecFeatureAction { finishWithCallback(HdmiControlManager.RESULT_SUCCESS); } } - - private void invokeCallback(int result) { - if (mCallback == null) { - return; - } - try { - mCallback.onComplete(result); - } catch (RemoteException e) { - // Do nothing. - } - } } diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java index a5477e865c40..978c25d0a8c6 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java @@ -16,13 +16,11 @@ package com.android.server.hdmi; -import android.annotation.Nullable; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.os.RemoteException; -import android.util.Slog; + import java.util.List; /** @@ -49,8 +47,6 @@ abstract class SystemAudioAction extends HdmiCecFeatureAction { // The target audio status of the action, whether to enable the system audio mode or not. protected boolean mTargetAudioStatus; - @Nullable private final IHdmiControlCallback mCallback; - private int mSendRetryCount = 0; /** @@ -64,11 +60,10 @@ abstract class SystemAudioAction extends HdmiCecFeatureAction { */ SystemAudioAction(HdmiCecLocalDevice source, int avrAddress, boolean targetStatus, IHdmiControlCallback callback) { - super(source); + super(source, callback); HdmiUtils.verifyAddressType(avrAddress, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); mAvrLogicalAddress = avrAddress; mTargetAudioStatus = targetStatus; - mCallback = callback; } // Seq #27 @@ -174,7 +169,7 @@ abstract class SystemAudioAction extends HdmiCecFeatureAction { } protected void startAudioStatusAction() { - addAndStartAction(new SystemAudioStatusAction(tv(), mAvrLogicalAddress, mCallback)); + addAndStartAction(new SystemAudioStatusAction(tv(), mAvrLogicalAddress, mCallbacks)); finish(); } @@ -194,17 +189,4 @@ abstract class SystemAudioAction extends HdmiCecFeatureAction { return; } } - - // TODO: if IHdmiControlCallback is general to other FeatureAction, - // move it into FeatureAction. - protected void finishWithCallback(int returnCode) { - if (mCallback != null) { - try { - mCallback.onComplete(returnCode); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to invoke callback.", e); - } - } - finish(); - } } diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java index 5d913d12b79f..b4af540b96f5 100644 --- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java +++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java @@ -16,14 +16,14 @@ package com.android.server.hdmi; -import android.annotation.Nullable; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.os.RemoteException; -import android.util.Slog; + import com.android.server.hdmi.HdmiControlService.SendMessageCallback; +import java.util.List; + /** * Action to update audio status (volume or mute) of audio amplifier */ @@ -34,13 +34,17 @@ final class SystemAudioStatusAction extends HdmiCecFeatureAction { private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 1; private final int mAvrAddress; - @Nullable private final IHdmiControlCallback mCallback; + + SystemAudioStatusAction( + HdmiCecLocalDevice source, int avrAddress, List<IHdmiControlCallback> callbacks) { + super(source, callbacks); + mAvrAddress = avrAddress; + } SystemAudioStatusAction(HdmiCecLocalDevice source, int avrAddress, IHdmiControlCallback callback) { - super(source); + super(source, callback); mAvrAddress = avrAddress; - mCallback = callback; } @Override @@ -97,17 +101,6 @@ final class SystemAudioStatusAction extends HdmiCecFeatureAction { finishWithCallback(HdmiControlManager.RESULT_SUCCESS); } - private void finishWithCallback(int returnCode) { - if (mCallback != null) { - try { - mCallback.onComplete(returnCode); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to invoke callback.", e); - } - } - finish(); - } - @Override void handleTimerEvent(int state) { if (mState != state) { diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java index afb47e831bdb..02f9ceb2d11d 100644 --- a/services/core/java/com/android/server/notification/NotificationDelegate.java +++ b/services/core/java/com/android/server/notification/NotificationDelegate.java @@ -55,9 +55,10 @@ public interface NotificationDelegate { void onNotificationBubbleChanged(String key, boolean isBubble, int flags); /** * Called when the state of {@link Notification.BubbleMetadata#FLAG_SUPPRESS_NOTIFICATION} - * changes. + * or {@link Notification.BubbleMetadata#FLAG_SUPPRESS_BUBBLE} changes. */ - void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed); + void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, + boolean isBubbleSuppressed); /** * Grant permission to read the specified URI to the package associated with the diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 73db7054cec5..6f39fea5dd95 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1269,7 +1269,7 @@ public class NotificationManagerService extends SystemService { } @Override - public void onNotificationBubbleChanged(String key, boolean isBubble, int flags) { + public void onNotificationBubbleChanged(String key, boolean isBubble, int bubbleFlags) { synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { @@ -1287,7 +1287,7 @@ public class NotificationManagerService extends SystemService { r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE; r.setFlagBubbleRemoved(false); if (r.getNotification().getBubbleMetadata() != null) { - r.getNotification().getBubbleMetadata().setFlags(flags); + r.getNotification().getBubbleMetadata().setFlags(bubbleFlags); } // Force isAppForeground true here, because for sysui's purposes we // want to adjust the flag behaviour. @@ -1299,7 +1299,8 @@ public class NotificationManagerService extends SystemService { } @Override - public void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed) { + public void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, + boolean isBubbleSuppressed) { synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { @@ -1308,26 +1309,36 @@ public class NotificationManagerService extends SystemService { // No data, do nothing return; } - boolean currentlySuppressed = data.isNotificationSuppressed(); - if (currentlySuppressed == isSuppressed) { - // No changes, do nothing - return; - } + int flags = data.getFlags(); - if (isSuppressed) { - flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; - } else { - flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; + boolean flagChanged = false; + if (data.isNotificationSuppressed() != isNotifSuppressed) { + flagChanged = true; + if (isNotifSuppressed) { + flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; + } else { + flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; + } + } + if (data.isBubbleSuppressed() != isBubbleSuppressed) { + flagChanged = true; + if (isBubbleSuppressed) { + flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE; + } else { + flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE; + } + } + if (flagChanged) { + data.setFlags(flags); + r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE; + mHandler.post( + new EnqueueNotificationRunnable(r.getUser().getIdentifier(), r, + true /* isAppForeground */)); } - data.setFlags(flags); - r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE; - mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(), r, - true /* isAppForeground */)); } } } - @Override /** * Grant permission to read the specified URI to the package specified in the * NotificationRecord associated with the given key. The callingUid represents the UID of @@ -1337,6 +1348,7 @@ public class NotificationManagerService extends SystemService { * user associated with the NotificationRecord, and this grant will fail when trying * to grant URI permissions across users. */ + @Override public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user, String packageName, int callingUid) { synchronized (mNotificationLock) { @@ -6117,18 +6129,27 @@ public class NotificationManagerService extends SystemService { } /** - * Some bubble specific flags only work if the app is foreground, this will strip those flags - * if the app wasn't foreground. + * Strips any flags from BubbleMetadata that wouldn't apply (e.g. app not foreground). */ private void updateNotificationBubbleFlags(NotificationRecord r, boolean isAppForeground) { - // Remove any bubble specific flags that only work when foregrounded Notification notification = r.getNotification(); Notification.BubbleMetadata metadata = notification.getBubbleMetadata(); - if (!isAppForeground && metadata != null) { + if (metadata == null) { + // Nothing to update + return; + } + if (!isAppForeground) { + // Auto expand only works if foreground int flags = metadata.getFlags(); flags &= ~Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE; metadata.setFlags(flags); } + if (!metadata.isBubbleSuppressable()) { + // If it's not suppressable remove the suppress flag + int flags = metadata.getFlags(); + flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_BUBBLE; + metadata.setFlags(flags); + } } private ShortcutHelper.ShortcutListener mShortcutListener = @@ -6504,9 +6525,11 @@ public class NotificationManagerService extends SystemService { } if (mReason == REASON_LISTENER_CANCEL - && (r.getNotification().flags & FLAG_BUBBLE) != 0) { + && r.getNotification().isBubbleNotification()) { + boolean isBubbleSuppressed = r.getNotification().getBubbleMetadata() != null + && r.getNotification().getBubbleMetadata().isBubbleSuppressed(); mNotificationDelegate.onBubbleNotificationSuppressionChanged( - r.getKey(), /* suppressed */ true); + r.getKey(), true /* suppressed */, isBubbleSuppressed); return; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b751503907fd..bc991634fb07 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -351,6 +351,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.policy.AttributeCache; import com.android.internal.telephony.CarrierAppUtils; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.CollectionUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; @@ -367,6 +368,7 @@ import com.android.server.ServiceThread; import com.android.server.SystemConfig; import com.android.server.SystemServerInitThreadPool; import com.android.server.Watchdog; +import com.android.server.apphibernation.AppHibernationManagerInternal; import com.android.server.compat.CompatChange; import com.android.server.compat.PlatformCompat; import com.android.server.net.NetworkPolicyManagerInternal; @@ -1385,7 +1387,6 @@ public class PackageManagerService extends IPackageManager.Stub public @Nullable String systemTextClassifierPackage; public @Nullable String overlayConfigSignaturePackage; public ViewCompiler viewCompiler; - public @Nullable String wellbeingPackage; public @Nullable String retailDemoPackage; public @Nullable String recentsPackage; public ComponentName resolveComponentName; @@ -1676,7 +1677,6 @@ public class PackageManagerService extends IPackageManager.Stub final @Nullable String mStorageManagerPackage; final @Nullable String mDefaultTextClassifierPackage; final @Nullable String mSystemTextClassifierPackageName; - final @Nullable String mWellbeingPackage; final @Nullable String mDocumenterPackage; final @Nullable String mConfiguratorPackage; final @Nullable String mAppPredictionServicePackage; @@ -2654,13 +2654,10 @@ public class PackageManagerService extends IPackageManager.Stub // If no apps are approved for the domain, resolve only to browsers if (approvedInfos.isEmpty()) { - // If the other profile has a result, include that and delegate to - // ResolveActivity + includeBrowser = true; if (xpDomainInfo != null && xpDomainInfo.highestApprovalLevel > DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE) { result.add(xpDomainInfo.resolveInfo); - } else { - includeBrowser = true; } } else { result.addAll(approvedInfos); @@ -2822,7 +2819,7 @@ public class PackageManagerService extends IPackageManager.Stub result.highestApprovalLevel = Math.max(mDomainVerificationManager .approvalLevelForDomain(ps, intent, resultTargetUser, flags, - riTargetUser.targetUserId), result.highestApprovalLevel); + parentUserId), result.highestApprovalLevel); } if (result != null && result.highestApprovalLevel <= DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE) { @@ -6216,7 +6213,6 @@ public class PackageManagerService extends IPackageManager.Stub mStorageManagerPackage = testParams.storageManagerPackage; mDefaultTextClassifierPackage = testParams.defaultTextClassifierPackage; mSystemTextClassifierPackageName = testParams.systemTextClassifierPackage; - mWellbeingPackage = testParams.wellbeingPackage; mRetailDemoPackage = testParams.retailDemoPackage; mRecentsPackage = testParams.recentsPackage; mDocumenterPackage = testParams.documenterPackage; @@ -6817,7 +6813,6 @@ public class PackageManagerService extends IPackageManager.Stub mDefaultTextClassifierPackage = getDefaultTextClassifierPackageName(); mSystemTextClassifierPackageName = getSystemTextClassifierPackageName(); - mWellbeingPackage = getWellbeingPackageName(); mDocumenterPackage = getDocumenterPackageName(); mConfiguratorPackage = getDeviceConfiguratorPackageName(); mAppPredictionServicePackage = getAppPredictionServicePackageName(); @@ -9991,6 +9986,7 @@ public class PackageManagerService extends IPackageManager.Stub false /*includeInstantApps*/, isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, parent.id, resolvedType, 0)); + flags |= PackageManager.MATCH_DEFAULT_ONLY; CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr( intent, resolvedType, flags, sourceUserId, parent.id); return xpDomainInfo != null; @@ -22845,7 +22841,9 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String getWellbeingPackageName() { - return ensureSystemPackageName(mContext.getString(R.string.config_defaultWellbeingPackage)); + return CollectionUtils.firstOrNull( + mContext.getSystemService(RoleManager.class).getRoleHolders( + RoleManager.ROLE_SYSTEM_WELLBEING)); } @Override @@ -23405,15 +23403,25 @@ public class PackageManagerService extends IPackageManager.Stub final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, true /* checkShell */, "stop package"); + boolean shouldUnhibernate = false; // writer synchronized (mLock) { final PackageSetting ps = mSettings.getPackageLPr(packageName); + if (ps.getStopped(userId) && !stopped) { + shouldUnhibernate = true; + } if (!shouldFilterApplicationLocked(ps, callingUid, userId) && mSettings.setPackageStoppedStateLPw(this, packageName, stopped, allowedByPermission, callingUid, userId)) { scheduleWritePackageRestrictionsLocked(userId); } } + if (shouldUnhibernate) { + AppHibernationManagerInternal ah = + mInjector.getLocalService(AppHibernationManagerInternal.class); + ah.setHibernatingForUser(packageName, userId, false); + ah.setHibernatingGlobally(packageName, false); + } } @Override @@ -26363,8 +26371,6 @@ public class PackageManagerService extends IPackageManager.Stub mDefaultTextClassifierPackage, mSystemTextClassifierPackageName); case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER: return filterOnlySystemPackages(mRequiredPermissionControllerPackage); - case PackageManagerInternal.PACKAGE_WELLBEING: - return filterOnlySystemPackages(mWellbeingPackage); case PackageManagerInternal.PACKAGE_DOCUMENTER: return filterOnlySystemPackages(mDocumenterPackage); case PackageManagerInternal.PACKAGE_CONFIGURATOR: diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java index ac50f29fbf32..b421cfc95295 100644 --- a/services/core/java/com/android/server/pm/permission/Permission.java +++ b/services/core/java/com/android/server/pm/permission/Permission.java @@ -304,10 +304,6 @@ public final class Permission { & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0; } - public boolean isWellbeing() { - return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0; - } - public boolean isDocumenter() { return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0; } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 2dfb6ff3e9a8..616058fc2562 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -3471,13 +3471,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Special permissions for the device configurator. allowed = true; } - if (!allowed && bp.isWellbeing() - && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( - PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM), - pkg.getPackageName())) { - // Special permission granted only to the OEM specified wellbeing app - allowed = true; - } if (!allowed && bp.isDocumenter() && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM), diff --git a/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java index 746a09882f93..688f0bf5e55f 100644 --- a/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java +++ b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java @@ -111,6 +111,8 @@ public class ProtoStreamUtils { static class StateResidencyResultUtils { public static void adjustTimeSinceBootToEpoch(StateResidencyResult[] stateResidencyResult, long startWallTime) { + if (stateResidencyResult == null) return; + for (int i = 0; i < stateResidencyResult.length; i++) { final int stateLength = stateResidencyResult[i].stateResidencyData.length; for (int j = 0; j < stateLength; j++) { @@ -320,6 +322,8 @@ public class ProtoStreamUtils { static class EnergyMeasurementUtils { public static void adjustTimeSinceBootToEpoch(EnergyMeasurement[] energyMeasurement, long startWallTime) { + if (energyMeasurement == null) return; + for (int i = 0; i < energyMeasurement.length; i++) { energyMeasurement[i].timestampMs += startWallTime; } @@ -539,6 +543,8 @@ public class ProtoStreamUtils { static class EnergyConsumerResultUtils { public static void adjustTimeSinceBootToEpoch(EnergyConsumerResult[] energyConsumerResult, long startWallTime) { + if (energyConsumerResult == null) return; + for (int i = 0; i < energyConsumerResult.length; i++) { energyConsumerResult[i].timestampMs += startWallTime; } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 8ffbb0a87dc0..546e420c1d59 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -1453,11 +1453,13 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed) { + public void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, + boolean isBubbleSuppressed) { enforceStatusBarService(); final long identity = Binder.clearCallingIdentity(); try { - mNotificationDelegate.onBubbleNotificationSuppressionChanged(key, isNotifSuppressed); + mNotificationDelegate.onBubbleNotificationSuppressionChanged(key, isNotifSuppressed, + isBubbleSuppressed); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 298128a6a222..5446a39fad86 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -253,6 +253,7 @@ import android.app.servertransaction.TransferSplashScreenViewStateItem; import android.app.usage.UsageEvents.Event; import android.content.ComponentName; import android.content.Intent; +import android.content.LocusId; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; @@ -551,6 +552,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A TaskDescription taskDescription; // the recents information for this activity + // The locusId associated with this activity, if set. + private LocusId mLocusId; + // These configurations are collected from application's resources based on size-sensitive // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800 // and drawable-sw400dp will be added to both as 400. @@ -6114,6 +6118,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A getTask().updateTaskDescription(); } + void setLocusId(LocusId locusId) { + if (Objects.equals(locusId, mLocusId)) return; + mLocusId = locusId; + final Task task = getTask(); + if (task != null) getTask().dispatchTaskInfoChangedIfNeeded(false /* force */); + } + + LocusId getLocusId() { + return mLocusId; + } + void setVoiceSessionLocked(IVoiceInteractionSession session) { voiceSession = session; pendingVoiceInteractionStart = false; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 0c77d9f1f724..3c5146c3a134 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -160,6 +160,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.IIntentSender; import android.content.Intent; +import android.content.LocusId; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; @@ -1942,6 +1943,21 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } + /** + * Sets the locusId for a particular activity. + * + * @param locusId the locusId to set. + * @param appToken the ActivityRecord's appToken. + */ + public void setLocusId(LocusId locusId, IBinder appToken) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInRootTaskLocked(appToken); + if (r != null) { + r.setLocusId(locusId); + } + } + } + NeededUriGrants collectGrants(Intent intent, ActivityRecord target) { if (target != null) { return mUgmInternal.checkGrantUriPermissionFromIntent(intent, diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 119ffb732283..1d45c6e1a371 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3856,6 +3856,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (newParent != null && newParent != mInputMethodSurfaceParent) { mInputMethodSurfaceParent = newParent; getPendingTransaction().reparent(mImeWindowsContainer.mSurfaceControl, newParent); + // When surface parent is removed, the relative layer will also be removed. We need to + // do a force update to make sure there is a layer set for the new parent. + assignRelativeLayerForIme(getPendingTransaction(), true /* forceUpdate */); scheduleAnimation(); } } @@ -4537,11 +4540,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } @Override - void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { + void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer, + boolean forceUpdate) { if (!mNeedsLayer) { return; } - super.assignRelativeLayer(t, relativeTo, layer); + super.assignRelativeLayer(t, relativeTo, layer, forceUpdate); mNeedsLayer = false; } } @@ -4631,6 +4635,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @Override void assignChildLayers(SurfaceControl.Transaction t) { + assignRelativeLayerForIme(t, false /* forceUpdate */); + super.assignChildLayers(t); + } + + private void assignRelativeLayerForIme(SurfaceControl.Transaction t, boolean forceUpdate) { mImeWindowsContainer.setNeedsLayer(); final WindowState imeTarget = mImeLayeringTarget; // In the case where we have an IME target that is not in split-screen mode IME @@ -4657,14 +4666,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mImeWindowsContainer.assignRelativeLayer(t, imeTarget.getSurfaceControl(), // TODO: We need to use an extra level on the app surface to ensure // this is always above SurfaceView but always below attached window. - 1); + 1, forceUpdate); } else if (mInputMethodSurfaceParent != null) { // The IME surface parent may not be its window parent's surface // (@see #computeImeParent), so set relative layer here instead of letting the window // parent to assign layer. - mImeWindowsContainer.assignRelativeLayer(t, mInputMethodSurfaceParent, 1); + mImeWindowsContainer.assignRelativeLayer(t, mInputMethodSurfaceParent, 1, forceUpdate); } - super.assignChildLayers(t); } /** @@ -4677,7 +4685,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * with {@link WindowState#assignLayer} */ void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) { - mImeWindowsContainer.setNeedsLayer(); child.assignRelativeLayer(t, mImeWindowsContainer.getSurfaceControl(), 1); } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 194350de385b..d992a4591a22 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4107,6 +4107,8 @@ class Task extends WindowContainer<WindowContainer> { : INVALID_TASK_ID; info.isFocused = isFocused(); info.isVisible = hasVisibleChildren(); + ActivityRecord topRecord = getTopNonFinishingActivity(); + info.mTopActivityLocusId = topRecord != null ? topRecord.getLocusId() : null; } @Nullable PictureInPictureParams getPictureInPictureParams() { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 76869e548fce..ed92fd08bef5 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -462,7 +462,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { mLastLeafTaskToFrontId = t.mTaskId; EventLogTags.writeWmTaskToFront(t.mUserId, t.mTaskId); - // Notifying only when a leak task moved to front. Or the listeners would be notified + // Notifying only when a leaf task moved to front. Or the listeners would be notified // couple times from the leaf task all the way up to the root task. mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(t.getTaskInfo()); } diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index ee5c1f014895..dff621c5871a 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -406,6 +406,12 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { } } + if (taskDisplayArea == null && source != null) { + final TaskDisplayArea sourceDisplayArea = source.getDisplayArea(); + if (DEBUG) appendLog("display-area-from-source=" + sourceDisplayArea); + taskDisplayArea = sourceDisplayArea; + } + Task rootTask = (taskDisplayArea == null && task != null) ? task.getRootTask() : null; if (rootTask != null) { @@ -413,12 +419,6 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { taskDisplayArea = rootTask.getDisplayArea(); } - if (taskDisplayArea == null && source != null) { - final TaskDisplayArea sourceDisplayArea = source.getDisplayArea(); - if (DEBUG) appendLog("display-area-from-source=" + sourceDisplayArea); - taskDisplayArea = sourceDisplayArea; - } - if (taskDisplayArea == null && options != null) { final int callerDisplayId = options.getCallerDisplayId(); final DisplayContent dc = diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 0c4ff2fe6365..8d859584d5f5 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2241,15 +2241,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } } - void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { + void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer, + boolean forceUpdate) { final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo; - if (mSurfaceControl != null && changed) { + if (mSurfaceControl != null && (changed || forceUpdate)) { setRelativeLayer(t, relativeTo, layer); mLastLayer = layer; mLastRelativeToLayer = relativeTo; } } + void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { + assignRelativeLayer(t, relativeTo, layer, false /* forceUpdate */); + } + protected void setLayer(Transaction t, int layer) { // Route through surface animator to accommodate that our surface control might be diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp index 8c6d084fba99..a4a74af8a1d9 100644 --- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp +++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp @@ -135,7 +135,7 @@ static int getAnyPageAdvice(const Vma& vma) { static int compactProcess(int pid, VmaToAdviseFunc vmaToAdviseFunc) { ProcMemInfo meminfo(pid); std::vector<Vma> pageoutVmas, coldVmas; - auto vmaCollectorCb = [&](Vma vma) { + auto vmaCollectorCb = [&coldVmas,&pageoutVmas,&vmaToAdviseFunc](const Vma& vma) { int advice = vmaToAdviseFunc(vma); switch (advice) { case MADV_COLD: @@ -146,7 +146,7 @@ static int compactProcess(int pid, VmaToAdviseFunc vmaToAdviseFunc) { break; } }; - meminfo.ForEachVma(vmaCollectorCb); + meminfo.ForEachVmaFromMaps(vmaCollectorCb); int err = compactMemory(pageoutVmas, pid, MADV_PAGEOUT); if (!err) { diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp index 8efbaf577134..f0210eeb80e8 100644 --- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp +++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp @@ -643,7 +643,7 @@ private: } TracedRead last = {}; - auto lastSerialNo = mLastSerialNo; + auto lastSerialNo = mLastSerialNo < 0 ? pageReads[0].serialNo : mLastSerialNo; for (auto&& read : pageReads) { const auto expectedSerialNo = lastSerialNo + last.count; #ifdef VERBOSE_READ_LOGS @@ -676,8 +676,7 @@ private: // Second, report missing reads, if any. if (read.serialNo != expectedSerialNo) { - const auto readsMissing = read.serialNo - expectedSerialNo; - traceMissingReads(readsMissing); + traceMissingReads(expectedSerialNo, read.serialNo); } last = TracedRead{ @@ -721,9 +720,13 @@ private: ATRACE_END(); } - void traceMissingReads(int64_t count) { - const auto trace = android::base::StringPrintf("missing_page_reads: count=%lld", - static_cast<long long>(count)); + void traceMissingReads(int64_t expectedSerialNo, int64_t readSerialNo) { + const auto readsMissing = readSerialNo - expectedSerialNo; + const auto trace = + android::base::StringPrintf("missing_page_reads: count=%lld, range [%lld,%lld)", + static_cast<long long>(readsMissing), + static_cast<long long>(expectedSerialNo), + static_cast<long long>(readSerialNo)); ATRACE_BEGIN(trace.c_str()); ATRACE_END(); } @@ -874,7 +877,7 @@ private: std::atomic<bool> mStopReceiving = false; std::atomic<bool> mReadLogsEnabled = false; std::chrono::milliseconds mWaitOnEofInterval{WaitOnEofMinInterval}; - int64_t mLastSerialNo{1}; + int64_t mLastSerialNo{-1}; /** Tracks which files have been requested */ std::unordered_set<FileIdx> mRequestedFiles; }; diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp index 757381dff80a..945694649f92 100644 --- a/services/core/jni/gnss/GnssMeasurementCallback.cpp +++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp @@ -131,7 +131,7 @@ void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) { "([I)Landroid/location/CorrelationVector$Builder;"); method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond = env->GetMethodID(class_correlationVectorBuilder, "setFrequencyOffsetMetersPerSecond", - "(I)Landroid/location/CorrelationVector$Builder;"); + "(D)Landroid/location/CorrelationVector$Builder;"); method_correlationVectorBuilderSetSamplingStartMeters = env->GetMethodID(class_correlationVectorBuilder, "setSamplingStartMeters", "(D)Landroid/location/CorrelationVector$Builder;"); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 9d2503af2044..2c1c9a957d85 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -5774,6 +5774,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (generationResult != KeyChain.KEY_GEN_SUCCESS) { Log.e(LOG_TAG, String.format( "KeyChain failed to generate a keypair, error %d.", generationResult)); + logGenerateKeyPairFailure(caller, isCredentialManagementApp); switch (generationResult) { case KeyChain.KEY_GEN_STRONGBOX_UNAVAILABLE: throw new ServiceSpecificException( @@ -5783,7 +5784,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { throw new UnsupportedOperationException( "Device does not support Device ID attestation."); default: - logGenerateKeyPairFailure(caller, isCredentialManagementApp); return false; } } @@ -7679,15 +7679,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private void sendActiveAdminCommand(String action, Bundle extras, @UserIdInt int userId, ComponentName receiverComponent) { - if (VERBOSE_LOG) { - Slog.v(LOG_TAG, "sending intent " + action + " to " - + receiverComponent.flattenToShortString() + " on user " + userId); - } final Intent intent = new Intent(action); intent.setComponent(receiverComponent); if (extras != null) { intent.putExtras(extras); } + if (VERBOSE_LOG) { + Slog.v(LOG_TAG, "sendActiveAdminCommand(): broadcasting " + action + " to " + + receiverComponent.flattenToShortString() + " on user " + userId); + } mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); } @@ -12541,10 +12541,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { extras.putBoolean(DeviceAdminReceiver.EXTRA_OPERATION_SAFETY_STATE, isSafe); if (mOwners.hasDeviceOwner()) { + if (VERBOSE_LOG) Slog.v(LOG_TAG, "Notifying DO"); sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED, extras); } for (int profileOwnerId : mOwners.getProfileOwnerKeys()) { + if (VERBOSE_LOG) Slog.v(LOG_TAG, "Notifying PO for user " + profileOwnerId); sendProfileOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED, extras, profileOwnerId); } @@ -13724,6 +13726,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mInjector.binderWithCleanCallingIdentity(() -> { // Clear restriction as user. final UserHandle parentUser = mUserManager.getProfileParent(UserHandle.of(userId)); + if (parentUser == null) { + throw new IllegalStateException(String.format("User %d is not a profile", userId)); + } if (!parentUser.isSystem()) { throw new IllegalStateException( String.format("Only the profile owner of a managed profile on the" diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java index 257fc640f93c..86437a27a64d 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java @@ -60,7 +60,7 @@ final class OneTimeSafetyChecker implements DevicePolicySafetyChecker { mOperation = operation; mReason = reason; mRealSafetyChecker = service.getDevicePolicySafetyChecker(); - Slog.i(TAG, "OneTimeSafetyChecker constructor: operation= " + operationToString(operation) + Slog.i(TAG, "OneTimeSafetyChecker constructor: operation=" + operationToString(operation) + ", reason=" + operationSafetyReasonToString(reason) + ", realChecker=" + mRealSafetyChecker + ", maxDuration=" + SELF_DESTRUCT_TIMEOUT_MS + "ms"); diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt index 6e27b3a8166c..e853fd341ae5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt @@ -287,6 +287,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { whenever(mocks.settings.internalVersion).thenReturn(DEFAULT_VERSION_INFO) whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) + whenever(mocks.settings.snapshot()).thenReturn(mocks.settings) whenever(mocks.packageAbiHelper.derivePackageAbi( any(AndroidPackage::class.java), anyBoolean(), nullable(), any(File::class.java))) { android.util.Pair(PackageAbiHelper.Abis("", ""), diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt new file mode 100644 index 000000000000..a0e208f662e3 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt @@ -0,0 +1,81 @@ +/* + * 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.server.pm + +import android.os.Build +import com.android.server.apphibernation.AppHibernationManagerInternal +import com.android.server.testutils.whenever +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(JUnit4::class) +class PackageManagerServiceHibernationTests { + + companion object { + val TEST_PACKAGE_NAME = "test.package" + val TEST_USER_ID = 0 + } + + @Rule + @JvmField + val rule = MockSystemRule() + + @Mock + lateinit var appHibernationManager: AppHibernationManagerInternal + + @Before + @Throws(Exception::class) + fun setup() { + MockitoAnnotations.initMocks(this) + rule.system().stageNominalSystemState() + whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java)) + .thenReturn(appHibernationManager) + } + + @Test + fun testExitForceStopExitsHibernation() { + rule.system().stageScanExistingPackage( + TEST_PACKAGE_NAME, + 1L, + rule.system().dataAppDirectory) + val pm = createPackageManagerService() + rule.system().validateFinalState() + val ps = pm.getPackageSetting(TEST_PACKAGE_NAME) + ps!!.setStopped(true, TEST_USER_ID) + + pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID) + verify(appHibernationManager).setHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID, false) + verify(appHibernationManager).setHibernatingGlobally(TEST_PACKAGE_NAME, false) + } + + private fun createPackageManagerService(): PackageManagerService { + return PackageManagerService(rule.mocks().injector, + false /*coreOnly*/, + false /*factoryTest*/, + MockSystem.DEFAULT_VERSION_INFO.fingerprint, + false /*isEngBuild*/, + false /*isUserDebugBuild*/, + Build.VERSION_CODES.CUR_DEVELOPMENT, + Build.VERSION.INCREMENTAL) + } +} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java deleted file mode 100644 index 170f561aa2da..000000000000 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * 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.server.accessibility; - - -import static android.view.accessibility.AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; -import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS; -import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS; -import static android.view.accessibility.AccessibilityNodeInfo.ROOT_NODE_ID; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.app.Instrumentation; -import android.content.Context; -import android.os.RemoteException; -import android.view.AccessibilityInteractionController; -import android.view.View; -import android.view.ViewRootImpl; -import android.view.WindowManager; -import android.view.accessibility.AccessibilityNodeIdManager; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityNodeProvider; -import android.view.accessibility.IAccessibilityInteractionConnectionCallback; -import android.widget.FrameLayout; -import android.widget.TextView; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -/** - * Tests that verify expected node and prefetched node results when finding a view by node id. We - * send some requests to the controller via View methods to control message timing. - */ -@RunWith(AndroidJUnit4.class) -public class AccessibilityInteractionControllerNodeRequestsTest { - private AccessibilityInteractionController mAccessibilityInteractionController; - @Mock - private IAccessibilityInteractionConnectionCallback mMockClientCallback1; - @Mock - private IAccessibilityInteractionConnectionCallback mMockClientCallback2; - - @Captor - private ArgumentCaptor<AccessibilityNodeInfo> mFindInfoCaptor; - @Captor private ArgumentCaptor<List<AccessibilityNodeInfo>> mPrefetchInfoListCaptor; - - private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); - private static final int MOCK_CLIENT_1_THREAD_AND_PROCESS_ID = 1; - private static final int MOCK_CLIENT_2_THREAD_AND_PROCESS_ID = 2; - - private static final String FRAME_LAYOUT_DESCRIPTION = "frameLayout"; - private static final String TEXT_VIEW_1_DESCRIPTION = "textView1"; - private static final String TEXT_VIEW_2_DESCRIPTION = "textView2"; - - private TestFrameLayout mFrameLayout; - private TestTextView mTextView1; - private TestTextView2 mTextView2; - - private boolean mSendClient1RequestForTextAfterTextPrefetched; - private boolean mSendClient2RequestForTextAfterTextPrefetched; - private boolean mSendRequestForTextAndIncludeUnImportantViews; - private int mMockClient1InteractionId; - private int mMockClient2InteractionId; - - @Before - public void setUp() throws Throwable { - MockitoAnnotations.initMocks(this); - - mInstrumentation.runOnMainSync(() -> { - final Context context = mInstrumentation.getTargetContext(); - final ViewRootImpl viewRootImpl = new ViewRootImpl(context, context.getDisplay()); - - mFrameLayout = new TestFrameLayout(context); - mTextView1 = new TestTextView(context); - mTextView2 = new TestTextView2(context); - - mFrameLayout.addView(mTextView1); - mFrameLayout.addView(mTextView2); - - // The controller retrieves views through this manager, and registration happens on - // when attached to a window, which we don't have. We can simply reference FrameLayout - // with ROOT_NODE_ID - AccessibilityNodeIdManager.getInstance().registerViewWithId( - mTextView1, mTextView1.getAccessibilityViewId()); - AccessibilityNodeIdManager.getInstance().registerViewWithId( - mTextView2, mTextView2.getAccessibilityViewId()); - - try { - viewRootImpl.setView(mFrameLayout, new WindowManager.LayoutParams(), null); - - } catch (WindowManager.BadTokenException e) { - // activity isn't running, we will ignore BadTokenException. - } - - mAccessibilityInteractionController = - new AccessibilityInteractionController(viewRootImpl); - }); - - } - - @After - public void tearDown() throws Throwable { - AccessibilityNodeIdManager.getInstance().unregisterViewWithId( - mTextView1.getAccessibilityViewId()); - AccessibilityNodeIdManager.getInstance().unregisterViewWithId( - mTextView2.getAccessibilityViewId()); - } - - /** - * Tests a basic request for the root node with prefetch flag - * {@link AccessibilityNodeInfo#FLAG_PREFETCH_DESCENDANTS} - * - * @throws RemoteException - */ - @Test - public void testFindRootView_withOneClient_shouldReturnRootNodeAndPrefetchDescendants() - throws RemoteException { - // Request for our FrameLayout - sendNodeRequestToController(ROOT_NODE_ID, mMockClientCallback1, - mMockClient1InteractionId, FLAG_PREFETCH_DESCENDANTS); - mInstrumentation.waitForIdleSync(); - - // Verify we get FrameLayout - verify(mMockClientCallback1).setFindAccessibilityNodeInfoResult( - mFindInfoCaptor.capture(), eq(mMockClient1InteractionId)); - AccessibilityNodeInfo infoSentToService = mFindInfoCaptor.getValue(); - assertEquals(FRAME_LAYOUT_DESCRIPTION, infoSentToService.getContentDescription()); - - verify(mMockClientCallback1).setPrefetchAccessibilityNodeInfoResult( - mPrefetchInfoListCaptor.capture(), eq(mMockClient1InteractionId)); - // The descendants are our two TextViews - List<AccessibilityNodeInfo> prefetchedNodes = mPrefetchInfoListCaptor.getValue(); - assertEquals(2, prefetchedNodes.size()); - assertEquals(TEXT_VIEW_1_DESCRIPTION, prefetchedNodes.get(0).getContentDescription()); - assertEquals(TEXT_VIEW_2_DESCRIPTION, prefetchedNodes.get(1).getContentDescription()); - - } - - /** - * Tests a basic request for TestTextView1's node with prefetch flag - * {@link AccessibilityNodeInfo#FLAG_PREFETCH_SIBLINGS} - * - * @throws RemoteException - */ - @Test - public void testFindTextView_withOneClient_shouldReturnNodeAndPrefetchedSiblings() - throws RemoteException { - // Request for TextView1 - sendNodeRequestToController(AccessibilityNodeInfo.makeNodeId( - mTextView1.getAccessibilityViewId(), AccessibilityNodeProvider.HOST_VIEW_ID), - mMockClientCallback1, mMockClient1InteractionId, FLAG_PREFETCH_SIBLINGS); - mInstrumentation.waitForIdleSync(); - - // Verify we get TextView1 - verify(mMockClientCallback1).setFindAccessibilityNodeInfoResult( - mFindInfoCaptor.capture(), eq(mMockClient1InteractionId)); - AccessibilityNodeInfo infoSentToService = mFindInfoCaptor.getValue(); - assertEquals(TEXT_VIEW_1_DESCRIPTION, infoSentToService.getContentDescription()); - - // Verify the prefetched sibling of TextView1 is TextView2 - verify(mMockClientCallback1).setPrefetchAccessibilityNodeInfoResult( - mPrefetchInfoListCaptor.capture(), eq(mMockClient1InteractionId)); - // TextView2 is the prefetched sibling - List<AccessibilityNodeInfo> prefetchedNodes = mPrefetchInfoListCaptor.getValue(); - assertEquals(1, prefetchedNodes.size()); - assertEquals(TEXT_VIEW_2_DESCRIPTION, prefetchedNodes.get(0).getContentDescription()); - } - - /** - * Tests a series of controller requests to prevent prefetching. - * Request 1: Client 1 requests the root node - * Request 2: When the root node is initialized in - * {@link TestFrameLayout#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}, - * Client 2 requests TestTextView1's node - * - * Request 2 on the queue prevents prefetching for Request 1. - * - * @throws RemoteException - */ - @Test - public void testFindRootAndTextNodes_withTwoClients_shouldPreventClient1Prefetch() - throws RemoteException { - mFrameLayout.setAccessibilityDelegate(new View.AccessibilityDelegate() { - @Override - public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(host, info); - final long nodeId = AccessibilityNodeInfo.makeNodeId( - mTextView1.getAccessibilityViewId(), - AccessibilityNodeProvider.HOST_VIEW_ID); - - // Enqueue a request when this node is found from a different service for - // TextView1 - sendNodeRequestToController(nodeId, mMockClientCallback2, - mMockClient2InteractionId, FLAG_PREFETCH_SIBLINGS); - } - }); - // Client 1 request for FrameLayout - sendNodeRequestToController(ROOT_NODE_ID, mMockClientCallback1, - mMockClient1InteractionId, FLAG_PREFETCH_DESCENDANTS); - - mInstrumentation.waitForIdleSync(); - - // Verify client 1 gets FrameLayout - verify(mMockClientCallback1).setFindAccessibilityNodeInfoResult( - mFindInfoCaptor.capture(), eq(mMockClient1InteractionId)); - AccessibilityNodeInfo infoSentToService = mFindInfoCaptor.getValue(); - assertEquals(FRAME_LAYOUT_DESCRIPTION, infoSentToService.getContentDescription()); - - // The second request is put in the queue in the FrameLayout's onInitializeA11yNodeInfo, - // meaning prefetching is interrupted and does not even begin for the first request - verify(mMockClientCallback1, never()) - .setPrefetchAccessibilityNodeInfoResult(anyList(), anyInt()); - - // Verify client 2 gets TextView1 - verify(mMockClientCallback2).setFindAccessibilityNodeInfoResult( - mFindInfoCaptor.capture(), eq(mMockClient2InteractionId)); - infoSentToService = mFindInfoCaptor.getValue(); - assertEquals(TEXT_VIEW_1_DESCRIPTION, infoSentToService.getContentDescription()); - - // Verify the prefetched sibling of TextView1 is TextView2 (FLAG_PREFETCH_SIBLINGS) - verify(mMockClientCallback2).setPrefetchAccessibilityNodeInfoResult( - mPrefetchInfoListCaptor.capture(), eq(mMockClient2InteractionId)); - List<AccessibilityNodeInfo> prefetchedNodes = mPrefetchInfoListCaptor.getValue(); - assertEquals(1, prefetchedNodes.size()); - assertEquals(TEXT_VIEW_2_DESCRIPTION, prefetchedNodes.get(0).getContentDescription()); - } - - /** - * Tests a series of controller same-service requests to interrupt prefetching and satisfy a - * pending node request. - * Request 1: Request the root node - * Request 2: When TextTextView1's node is initialized as part of Request 1's prefetching, - * request TestTextView1's node - * - * Request 1 prefetches TestTextView1's node, is interrupted by a pending request, and checks - * if its prefetched nodes satisfy any pending requests. It satisfies Request 2's request for - * TestTextView1's node. Request 2 is fulfilled, so it is removed from queue and does not - * prefetch. - * - * @throws RemoteException - */ - @Test - public void testFindRootAndTextNode_withOneClient_shouldInterruptPrefetchAndSatisfyPendingMsg() - throws RemoteException { - mSendClient1RequestForTextAfterTextPrefetched = true; - - mTextView1.setAccessibilityDelegate(new View.AccessibilityDelegate(){ - @Override - public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setContentDescription(TEXT_VIEW_1_DESCRIPTION); - final long nodeId = AccessibilityNodeInfo.makeNodeId( - mTextView1.getAccessibilityViewId(), - AccessibilityNodeProvider.HOST_VIEW_ID); - - if (mSendClient1RequestForTextAfterTextPrefetched) { - // Prevent a loop when processing second request - mSendClient1RequestForTextAfterTextPrefetched = false; - // TextView1 is prefetched here after the FrameLayout is found. Now enqueue a - // same-client request for TextView1 - sendNodeRequestToController(nodeId, mMockClientCallback1, - ++mMockClient1InteractionId, FLAG_PREFETCH_SIBLINGS); - - } - } - }); - // Client 1 requests FrameLayout - sendNodeRequestToController(ROOT_NODE_ID, mMockClientCallback1, - mMockClient1InteractionId, FLAG_PREFETCH_DESCENDANTS); - - // Flush out all messages - mInstrumentation.waitForIdleSync(); - - // When TextView1 is prefetched for FrameLayout, we put a message on the queue in - // TextView1's onInitializeA11yNodeInfo that requests for TextView1. The service thus get - // two node results for FrameLayout and TextView1. - verify(mMockClientCallback1, times(2)) - .setFindAccessibilityNodeInfoResult(mFindInfoCaptor.capture(), anyInt()); - - List<AccessibilityNodeInfo> foundNodes = mFindInfoCaptor.getAllValues(); - assertEquals(FRAME_LAYOUT_DESCRIPTION, foundNodes.get(0).getContentDescription()); - assertEquals(TEXT_VIEW_1_DESCRIPTION, foundNodes.get(1).getContentDescription()); - - // The controller will look at FrameLayout's prefetched nodes and find matching nodes in - // pending requests. The prefetched TextView1 matches the second request. The second - // request was removed from queue and prefetching for this request never occurred. - verify(mMockClientCallback1, times(1)) - .setPrefetchAccessibilityNodeInfoResult(mPrefetchInfoListCaptor.capture(), - eq(mMockClient1InteractionId - 1)); - List<AccessibilityNodeInfo> prefetchedNodes = mPrefetchInfoListCaptor.getValue(); - assertEquals(1, prefetchedNodes.size()); - assertEquals(TEXT_VIEW_1_DESCRIPTION, prefetchedNodes.get(0).getContentDescription()); - } - - /** - * Like above, but tests a series of controller requests from different services to interrupt - * prefetching and satisfy a pending node request. - * - * @throws RemoteException - */ - @Test - public void testFindRootAndTextNode_withTwoClients_shouldInterruptPrefetchAndSatisfyPendingMsg() - throws RemoteException { - mSendClient2RequestForTextAfterTextPrefetched = true; - mTextView1.setAccessibilityDelegate(new View.AccessibilityDelegate(){ - @Override - public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setContentDescription(TEXT_VIEW_1_DESCRIPTION); - final long nodeId = AccessibilityNodeInfo.makeNodeId( - mTextView1.getAccessibilityViewId(), - AccessibilityNodeProvider.HOST_VIEW_ID); - - if (mSendClient2RequestForTextAfterTextPrefetched) { - mSendClient2RequestForTextAfterTextPrefetched = false; - // TextView1 is prefetched here. Now enqueue client 2's request for - // TextView1 - sendNodeRequestToController(nodeId, mMockClientCallback2, - mMockClient2InteractionId, FLAG_PREFETCH_SIBLINGS); - } - } - }); - // Client 1 requests FrameLayout - sendNodeRequestToController(ROOT_NODE_ID, mMockClientCallback1, - mMockClient1InteractionId, FLAG_PREFETCH_DESCENDANTS); - - mInstrumentation.waitForIdleSync(); - - // Verify client 1 gets FrameLayout - verify(mMockClientCallback1, times(1)) - .setFindAccessibilityNodeInfoResult(mFindInfoCaptor.capture(), anyInt()); - assertEquals(FRAME_LAYOUT_DESCRIPTION, - mFindInfoCaptor.getValue().getContentDescription()); - - // Verify client 1 has prefetched nodes - verify(mMockClientCallback1, times(1)) - .setPrefetchAccessibilityNodeInfoResult(mPrefetchInfoListCaptor.capture(), - eq(mMockClient1InteractionId)); - - // Verify client 1's only prefetched node is TextView1 - List<AccessibilityNodeInfo> prefetchedNodes = mPrefetchInfoListCaptor.getValue(); - assertEquals(1, prefetchedNodes.size()); - assertEquals(TEXT_VIEW_1_DESCRIPTION, prefetchedNodes.get(0).getContentDescription()); - - // Verify client 2 gets TextView1 - verify(mMockClientCallback2, times(1)) - .setFindAccessibilityNodeInfoResult(mFindInfoCaptor.capture(), anyInt()); - - assertEquals(TEXT_VIEW_1_DESCRIPTION, mFindInfoCaptor.getValue().getContentDescription()); - - // The second request was removed from queue and prefetching for this client request never - // occurred as it was satisfied. - verify(mMockClientCallback2, never()) - .setPrefetchAccessibilityNodeInfoResult(anyList(), anyInt()); - - } - - @Test - public void testFindNodeById_withTwoDifferentPrefetchFlags_shouldNotSatisfyPendingRequest() - throws RemoteException { - mSendRequestForTextAndIncludeUnImportantViews = true; - mTextView1.setAccessibilityDelegate(new View.AccessibilityDelegate(){ - @Override - public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setContentDescription(TEXT_VIEW_1_DESCRIPTION); - final long nodeId = AccessibilityNodeInfo.makeNodeId( - mTextView1.getAccessibilityViewId(), - AccessibilityNodeProvider.HOST_VIEW_ID); - - if (mSendRequestForTextAndIncludeUnImportantViews) { - mSendRequestForTextAndIncludeUnImportantViews = false; - // TextView1 is prefetched here for client 1. Now enqueue a request from a - // different client that holds different fetch flags for TextView1 - sendNodeRequestToController(nodeId, mMockClientCallback2, - mMockClient2InteractionId, - FLAG_PREFETCH_SIBLINGS | FLAG_INCLUDE_NOT_IMPORTANT_VIEWS); - } - } - }); - - // Mockito does not make copies of objects when called. It holds references, so - // the captor would point to client 2's results after all requests are processed. Verify - // prefetched node immediately - doAnswer(invocation -> { - List<AccessibilityNodeInfo> prefetched = invocation.getArgument(0); - assertEquals(TEXT_VIEW_1_DESCRIPTION, prefetched.get(0).getContentDescription()); - return null; - }).when(mMockClientCallback1).setPrefetchAccessibilityNodeInfoResult(anyList(), - eq(mMockClient1InteractionId)); - - // Client 1 requests FrameLayout - sendNodeRequestToController(ROOT_NODE_ID, mMockClientCallback1, - mMockClient1InteractionId, FLAG_PREFETCH_DESCENDANTS); - - mInstrumentation.waitForIdleSync(); - - // Verify client 1 gets FrameLayout - verify(mMockClientCallback1, times(1)) - .setFindAccessibilityNodeInfoResult(mFindInfoCaptor.capture(), - eq(mMockClient1InteractionId)); - - assertEquals(FRAME_LAYOUT_DESCRIPTION, - mFindInfoCaptor.getValue().getContentDescription()); - - // Verify client 1 has prefetched results. The only prefetched node is TextView1 - // (from above doAnswer) - verify(mMockClientCallback1, times(1)) - .setPrefetchAccessibilityNodeInfoResult(mPrefetchInfoListCaptor.capture(), - eq(mMockClient1InteractionId)); - - // Verify client 2 gets TextView1 - verify(mMockClientCallback2, times(1)) - .setFindAccessibilityNodeInfoResult(mFindInfoCaptor.capture(), - eq(mMockClient2InteractionId)); - assertEquals(TEXT_VIEW_1_DESCRIPTION, - mFindInfoCaptor.getValue().getContentDescription()); - // Verify client 2 has TextView2 as a prefetched node - verify(mMockClientCallback2, times(1)) - .setPrefetchAccessibilityNodeInfoResult(mPrefetchInfoListCaptor.capture(), - eq(mMockClient2InteractionId)); - List<AccessibilityNodeInfo> prefetchedNode = mPrefetchInfoListCaptor.getValue(); - assertEquals(1, prefetchedNode.size()); - assertEquals(TEXT_VIEW_2_DESCRIPTION, prefetchedNode.get(0).getContentDescription()); - } - - private void sendNodeRequestToController(long requestedNodeId, - IAccessibilityInteractionConnectionCallback callback, int interactionId, - int prefetchFlags) { - final int processAndThreadId = callback == mMockClientCallback1 - ? MOCK_CLIENT_1_THREAD_AND_PROCESS_ID - : MOCK_CLIENT_2_THREAD_AND_PROCESS_ID; - - mAccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdClientThread( - requestedNodeId, - null, interactionId, - callback, prefetchFlags, - processAndThreadId, - processAndThreadId, null, null); - - } - - private class TestFrameLayout extends FrameLayout { - - TestFrameLayout(Context context) { - super(context); - } - - @Override - public int getWindowVisibility() { - // We aren't attached to a window so let's pretend - return VISIBLE; - } - - @Override - public boolean isShown() { - // Controller check - return true; - } - - @Override - public int getAccessibilityViewId() { - // static id doesn't reset after tests so return the same one - return 0; - } - - @Override - public void addChildrenForAccessibility(ArrayList<View> outChildren) { - // ViewGroup#addChildrenForAccessbility sorting logic will switch these two - outChildren.add(mTextView1); - outChildren.add(mTextView2); - } - - @Override - public boolean includeForAccessibility() { - return true; - } - - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setContentDescription(FRAME_LAYOUT_DESCRIPTION); - } - } - - private class TestTextView extends TextView { - TestTextView(Context context) { - super(context); - } - - @Override - public int getWindowVisibility() { - return VISIBLE; - } - - @Override - public boolean isShown() { - return true; - } - - @Override - public int getAccessibilityViewId() { - return 1; - } - - @Override - public boolean includeForAccessibility() { - return true; - } - - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setContentDescription(TEXT_VIEW_1_DESCRIPTION); - } - } - - private class TestTextView2 extends TextView { - TestTextView2(Context context) { - super(context); - } - - @Override - public int getWindowVisibility() { - return VISIBLE; - } - - @Override - public boolean isShown() { - return true; - } - - @Override - public int getAccessibilityViewId() { - return 2; - } - - @Override - public boolean includeForAccessibility() { - return true; - } - - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setContentDescription(TEXT_VIEW_2_DESCRIPTION); - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java b/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java index 1efce39e00fa..3231f6204a12 100644 --- a/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java +++ b/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java @@ -57,45 +57,58 @@ public final class MeasuredEnergySnapshotTest { private static final SparseArray<EnergyConsumer> SOME_ID_CONSUMER_MAP = createIdToConsumerMap( CONSUMER_DISPLAY); + private static final int VOLTAGE_0 = 4_000; + private static final int VOLTAGE_1 = 3_500; + private static final int VOLTAGE_2 = 3_100; + private static final int VOLTAGE_3 = 3_000; + private static final int VOLTAGE_4 = 2_800; + // Elements in each results are purposefully out of order. - private static final EnergyConsumerResult[] RESULTS_0 = new EnergyConsumerResult[] { - createEnergyConsumerResult(CONSUMER_OTHER_0.id, 90, new int[] {47, 3}, new long[] {14, 13}), - createEnergyConsumerResult(CONSUMER_DISPLAY.id, 14, null, null), - createEnergyConsumerResult(CONSUMER_OTHER_1.id, 0, null, null), - // No CONSUMER_OTHER_2 + private static final EnergyConsumerResult[] RESULTS_0 = new EnergyConsumerResult[]{ + createEnergyConsumerResult(CONSUMER_OTHER_0.id, 90_000, new int[]{47, 3}, + new long[]{14_000, 13_000}), + createEnergyConsumerResult(CONSUMER_DISPLAY.id, 14_000, null, null), + createEnergyConsumerResult(CONSUMER_OTHER_1.id, 0, null, null), + // No CONSUMER_OTHER_2 }; - private static final EnergyConsumerResult[] RESULTS_1 = new EnergyConsumerResult[] { - createEnergyConsumerResult(CONSUMER_DISPLAY.id, 24, null, null), - createEnergyConsumerResult(CONSUMER_OTHER_0.id, 90, new int[] {47, 3}, new long[] {14, 13}), - createEnergyConsumerResult(CONSUMER_OTHER_2.id, 12, new int[] {6}, new long[] {10}), - createEnergyConsumerResult(CONSUMER_OTHER_1.id, 12_000, null, null), + private static final EnergyConsumerResult[] RESULTS_1 = new EnergyConsumerResult[]{ + createEnergyConsumerResult(CONSUMER_DISPLAY.id, 24_000, null, null), + createEnergyConsumerResult(CONSUMER_OTHER_0.id, 90_000, new int[]{47, 3}, + new long[]{14_000, 13_000}), + createEnergyConsumerResult(CONSUMER_OTHER_2.id, 12_000, new int[]{6}, + new long[]{10_000}), + createEnergyConsumerResult(CONSUMER_OTHER_1.id, 12_000_000, null, null), }; - private static final EnergyConsumerResult[] RESULTS_2 = new EnergyConsumerResult[] { - createEnergyConsumerResult(CONSUMER_DISPLAY.id, 36, null, null), - // No CONSUMER_OTHER_0 - // No CONSUMER_OTHER_1 - // No CONSUMER_OTHER_2 + private static final EnergyConsumerResult[] RESULTS_2 = new EnergyConsumerResult[]{ + createEnergyConsumerResult(CONSUMER_DISPLAY.id, 36_000, null, null), + // No CONSUMER_OTHER_0 + // No CONSUMER_OTHER_1 + // No CONSUMER_OTHER_2 }; - private static final EnergyConsumerResult[] RESULTS_3 = new EnergyConsumerResult[] { - // No CONSUMER_DISPLAY - createEnergyConsumerResult(CONSUMER_OTHER_2.id, 13, new int[] {6}, new long[] {10}), - createEnergyConsumerResult( - CONSUMER_OTHER_0.id, 190, new int[] {2, 3, 47, 7}, new long[] {9, 18, 14, 6}), - createEnergyConsumerResult(CONSUMER_OTHER_1.id, 12_000, null, null), + private static final EnergyConsumerResult[] RESULTS_3 = new EnergyConsumerResult[]{ + // No CONSUMER_DISPLAY + createEnergyConsumerResult(CONSUMER_OTHER_2.id, 13_000, new int[]{6}, + new long[]{10_000}), + createEnergyConsumerResult( + CONSUMER_OTHER_0.id, 190_000, new int[]{2, 3, 47, 7}, + new long[]{9_000, 18_000, 14_000, 6_000}), + createEnergyConsumerResult(CONSUMER_OTHER_1.id, 12_000_000, null, null), }; - private static final EnergyConsumerResult[] RESULTS_4 = new EnergyConsumerResult[] { - createEnergyConsumerResult(CONSUMER_DISPLAY.id, 43, null, null), - createEnergyConsumerResult( - CONSUMER_OTHER_0.id, 290, new int[] {7, 47, 3, 2}, new long[] {6, 14, 18, 11}), - // No CONSUMER_OTHER_1 - createEnergyConsumerResult(CONSUMER_OTHER_2.id, 165, new int[] {6, 47}, new long[] {10, 8}), + private static final EnergyConsumerResult[] RESULTS_4 = new EnergyConsumerResult[]{ + createEnergyConsumerResult(CONSUMER_DISPLAY.id, 43_000, null, null), + createEnergyConsumerResult( + CONSUMER_OTHER_0.id, 290_000, new int[]{7, 47, 3, 2}, + new long[]{6_000, 14_000, 18_000, 11_000}), + // No CONSUMER_OTHER_1 + createEnergyConsumerResult(CONSUMER_OTHER_2.id, 165_000, new int[]{6, 47}, + new long[]{10_000, 8_000}), }; @Test public void testUpdateAndGetDelta_empty() { final MeasuredEnergySnapshot snapshot = new MeasuredEnergySnapshot(ALL_ID_CONSUMER_MAP); - assertNull(snapshot.updateAndGetDelta(null)); - assertNull(snapshot.updateAndGetDelta(new EnergyConsumerResult[0])); + assertNull(snapshot.updateAndGetDelta(null, VOLTAGE_0)); + assertNull(snapshot.updateAndGetDelta(new EnergyConsumerResult[0], VOLTAGE_0)); } @Test @@ -103,69 +116,88 @@ public final class MeasuredEnergySnapshotTest { final MeasuredEnergySnapshot snapshot = new MeasuredEnergySnapshot(ALL_ID_CONSUMER_MAP); // results0 - MeasuredEnergyDeltaData delta = snapshot.updateAndGetDelta(RESULTS_0); + MeasuredEnergyDeltaData delta = snapshot.updateAndGetDelta(RESULTS_0, VOLTAGE_0); if (delta != null) { // null is fine here. If non-null, it better be uninteresting though. - assertEquals(UNAVAILABLE, delta.displayEnergyUJ); - assertNull(delta.otherTotalEnergyUJ); - assertNull(delta.otherUidEnergiesUJ); + assertEquals(UNAVAILABLE, delta.displayChargeUC); + assertNull(delta.otherTotalChargeUC); + assertNull(delta.otherUidChargesUC); } // results1 - delta = snapshot.updateAndGetDelta(RESULTS_1); + delta = snapshot.updateAndGetDelta(RESULTS_1, VOLTAGE_1); assertNotNull(delta); - assertEquals(24 - 14, delta.displayEnergyUJ); + long expectedChargeUC; + expectedChargeUC = calculateChargeConsumedUC(14_000, VOLTAGE_0, 24_000, VOLTAGE_1); + assertEquals(expectedChargeUC, delta.displayChargeUC); + + assertNotNull(delta.otherTotalChargeUC); - assertNotNull(delta.otherTotalEnergyUJ); - assertEquals(90 - 90, delta.otherTotalEnergyUJ[0]); - assertEquals(12_000 - 0, delta.otherTotalEnergyUJ[1]); - assertEquals(0, delta.otherTotalEnergyUJ[2]); // First good pull. Treat delta as 0. + expectedChargeUC = calculateChargeConsumedUC(90_000, VOLTAGE_0, 90_000, VOLTAGE_1); + assertEquals(expectedChargeUC, delta.otherTotalChargeUC[0]); + expectedChargeUC = calculateChargeConsumedUC(0, VOLTAGE_0, 12_000_000, VOLTAGE_1); + assertEquals(expectedChargeUC, delta.otherTotalChargeUC[1]); + assertEquals(0, delta.otherTotalChargeUC[2]); // First good pull. Treat delta as 0. - assertNotNull(delta.otherUidEnergiesUJ); - assertNullOrEmpty(delta.otherUidEnergiesUJ[0]); // No change in uid energies - assertNullOrEmpty(delta.otherUidEnergiesUJ[1]); - assertNullOrEmpty(delta.otherUidEnergiesUJ[2]); + assertNotNull(delta.otherUidChargesUC); + assertNullOrEmpty(delta.otherUidChargesUC[0]); // No change in uid energies + assertNullOrEmpty(delta.otherUidChargesUC[1]); + assertNullOrEmpty(delta.otherUidChargesUC[2]); // results2 - delta = snapshot.updateAndGetDelta(RESULTS_2); + delta = snapshot.updateAndGetDelta(RESULTS_2, VOLTAGE_2); assertNotNull(delta); - assertEquals(36 - 24, delta.displayEnergyUJ); - assertNull(delta.otherUidEnergiesUJ); - assertNull(delta.otherTotalEnergyUJ); + expectedChargeUC = calculateChargeConsumedUC(24_000, VOLTAGE_1, 36_000, VOLTAGE_2); + assertEquals(expectedChargeUC, delta.displayChargeUC); + assertNull(delta.otherUidChargesUC); + assertNull(delta.otherTotalChargeUC); // results3 - delta = snapshot.updateAndGetDelta(RESULTS_3); + delta = snapshot.updateAndGetDelta(RESULTS_3, VOLTAGE_3); assertNotNull(delta); - assertEquals(UNAVAILABLE, delta.displayEnergyUJ); + assertEquals(UNAVAILABLE, delta.displayChargeUC); + + assertNotNull(delta.otherTotalChargeUC); + + expectedChargeUC = calculateChargeConsumedUC(90_000, VOLTAGE_1, 190_000, VOLTAGE_3); + assertEquals(expectedChargeUC, delta.otherTotalChargeUC[0]); + expectedChargeUC = calculateChargeConsumedUC(12_000_000, VOLTAGE_1, 12_000_000, VOLTAGE_3); + assertEquals(expectedChargeUC, delta.otherTotalChargeUC[1]); + expectedChargeUC = calculateChargeConsumedUC(12_000, VOLTAGE_1, 13_000, VOLTAGE_3); + assertEquals(expectedChargeUC, delta.otherTotalChargeUC[2]); - assertNotNull(delta.otherTotalEnergyUJ); - assertEquals(190 - 90, delta.otherTotalEnergyUJ[0]); - assertEquals(12_000 - 12_000, delta.otherTotalEnergyUJ[1]); - assertEquals(13 - 12, delta.otherTotalEnergyUJ[2]); + assertNotNull(delta.otherUidChargesUC); - assertNotNull(delta.otherUidEnergiesUJ); - assertEquals(3, delta.otherUidEnergiesUJ[0].size()); - assertEquals(9 - 0, delta.otherUidEnergiesUJ[0].get(2)); - assertEquals(18 - 13, delta.otherUidEnergiesUJ[0].get(3)); - assertEquals(6 - 0, delta.otherUidEnergiesUJ[0].get(7)); - assertNullOrEmpty(delta.otherUidEnergiesUJ[1]); - assertNullOrEmpty(delta.otherUidEnergiesUJ[2]); + assertEquals(3, delta.otherUidChargesUC[0].size()); + expectedChargeUC = calculateChargeConsumedUC(0, VOLTAGE_1, 9_000, VOLTAGE_3); + assertEquals(expectedChargeUC, delta.otherUidChargesUC[0].get(2)); + expectedChargeUC = calculateChargeConsumedUC(13_000, VOLTAGE_1, 18_000, VOLTAGE_3); + assertEquals(expectedChargeUC, delta.otherUidChargesUC[0].get(3)); + expectedChargeUC = calculateChargeConsumedUC(0, VOLTAGE_1, 6_000, VOLTAGE_3); + assertEquals(expectedChargeUC, delta.otherUidChargesUC[0].get(7)); + assertNullOrEmpty(delta.otherUidChargesUC[1]); + assertNullOrEmpty(delta.otherUidChargesUC[2]); // results4 - delta = snapshot.updateAndGetDelta(RESULTS_4); + delta = snapshot.updateAndGetDelta(RESULTS_4, VOLTAGE_4); assertNotNull(delta); - assertEquals(43 - 36, delta.displayEnergyUJ); - - assertNotNull(delta.otherTotalEnergyUJ); - assertEquals(290 - 190, delta.otherTotalEnergyUJ[0]); - assertEquals(0, delta.otherTotalEnergyUJ[1]); // Not present (e.g. missing data) - assertEquals(165 - 13, delta.otherTotalEnergyUJ[2]); - - assertNotNull(delta.otherUidEnergiesUJ); - assertEquals(1, delta.otherUidEnergiesUJ[0].size()); - assertEquals(11 - 9, delta.otherUidEnergiesUJ[0].get(2)); - assertNullOrEmpty(delta.otherUidEnergiesUJ[1]); // Not present - assertEquals(1, delta.otherUidEnergiesUJ[2].size()); - assertEquals(8, delta.otherUidEnergiesUJ[2].get(47)); + expectedChargeUC = calculateChargeConsumedUC(36_000, VOLTAGE_2, 43_000, VOLTAGE_4); + assertEquals(expectedChargeUC, delta.displayChargeUC); + + assertNotNull(delta.otherTotalChargeUC); + expectedChargeUC = calculateChargeConsumedUC(190_000, VOLTAGE_3, 290_000, VOLTAGE_4); + assertEquals(expectedChargeUC, delta.otherTotalChargeUC[0]); + assertEquals(0, delta.otherTotalChargeUC[1]); // Not present (e.g. missing data) + expectedChargeUC = calculateChargeConsumedUC(13_000, VOLTAGE_3, 165_000, VOLTAGE_4); + assertEquals(expectedChargeUC, delta.otherTotalChargeUC[2]); + + assertNotNull(delta.otherUidChargesUC); + assertEquals(1, delta.otherUidChargesUC[0].size()); + expectedChargeUC = calculateChargeConsumedUC(9_000, VOLTAGE_3, 11_000, VOLTAGE_4); + assertEquals(expectedChargeUC, delta.otherUidChargesUC[0].get(2)); + assertNullOrEmpty(delta.otherUidChargesUC[1]); // Not present + assertEquals(1, delta.otherUidChargesUC[2].size()); + expectedChargeUC = calculateChargeConsumedUC(0, VOLTAGE_3, 8_000, VOLTAGE_4); + assertEquals(expectedChargeUC, delta.otherUidChargesUC[2].get(47)); } /** Test updateAndGetDelta() when the results have consumers absent from idToConsumerMap. */ @@ -174,19 +206,21 @@ public final class MeasuredEnergySnapshotTest { final MeasuredEnergySnapshot snapshot = new MeasuredEnergySnapshot(SOME_ID_CONSUMER_MAP); // results0 - MeasuredEnergyDeltaData delta = snapshot.updateAndGetDelta(RESULTS_0); + MeasuredEnergyDeltaData delta = snapshot.updateAndGetDelta(RESULTS_0, VOLTAGE_0); if (delta != null) { // null is fine here. If non-null, it better be uninteresting though. - assertEquals(UNAVAILABLE, delta.displayEnergyUJ); - assertNull(delta.otherTotalEnergyUJ); - assertNull(delta.otherUidEnergiesUJ); + assertEquals(UNAVAILABLE, delta.displayChargeUC); + assertNull(delta.otherTotalChargeUC); + assertNull(delta.otherUidChargesUC); } // results1 - delta = snapshot.updateAndGetDelta(RESULTS_1); + delta = snapshot.updateAndGetDelta(RESULTS_1, VOLTAGE_1); assertNotNull(delta); - assertEquals(24 - 14, delta.displayEnergyUJ); - assertNull(delta.otherTotalEnergyUJ); // Although in the results, they're not in the idMap - assertNull(delta.otherUidEnergiesUJ); + final long expectedChargeUC = + calculateChargeConsumedUC(14_000, VOLTAGE_0, 24_000, VOLTAGE_1); + assertEquals(expectedChargeUC, delta.displayChargeUC); + assertNull(delta.otherTotalChargeUC); // Although in the results, they're not in the idMap + assertNull(delta.otherUidChargesUC); } @Test @@ -234,6 +268,15 @@ public final class MeasuredEnergySnapshotTest { return ecr; } + private static long calculateChargeConsumedUC(long energyUWs0, long voltageMv0, long energyUWs1, + long voltageMv1) { + final long deltaEnergyUWs = energyUWs1 - energyUWs0; + final long avgVoltageMv = (voltageMv1 + voltageMv0 + 1) / 2; + + // Charge uC = Energy uWs * (1000 mV/V) / (voltage mV) + 0.5 (for rounding) + return (deltaEnergyUWs * 1000 + (avgVoltageMv / 2)) / avgVoltageMv; + } + private void assertNullOrEmpty(SparseLongArray a) { if (a != null) assertEquals("Array should be null or empty", 0, a.size()); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index cebdbbef2329..1905e2ff8461 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -6207,7 +6207,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { reset(mListeners); // Test: update suppression to true - mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true); + mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true, + false); waitForIdle(); // Check @@ -6218,7 +6219,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { reset(mListeners); // Test: update suppression to false - mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false); + mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false, + false); waitForIdle(); // Check diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 09a436c59e7b..f5d831bbe73e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -342,6 +342,25 @@ public class DisplayContentTests extends WindowTestsBase { verify(imeTarget.getRootDisplayArea()).placeImeContainer(imeContainer); } + @Test + public void testUpdateImeParent_forceUpdateRelativeLayer() { + final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer(); + final ActivityRecord activity = createActivityRecord(mDisplayContent); + + final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity, + "startingWin"); + startingWin.setHasSurface(true); + assertTrue(startingWin.canBeImeTarget()); + final SurfaceControl imeSurfaceParent = mock(SurfaceControl.class); + doReturn(imeSurfaceParent).when(mDisplayContent).computeImeParent(); + spyOn(imeContainer); + + mDisplayContent.updateImeParent(); + + // Force reassign the relative layer when the IME surface parent is changed. + verify(imeContainer).assignRelativeLayer(any(), eq(imeSurfaceParent), anyInt(), eq(true)); + } + /** * This tests stack movement between displays and proper stack's, task's and app token's display * container references updates. diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index 5239462a1ec0..ed5729400a39 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -195,7 +195,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { } @Test - public void testUsesTasksDisplayAreaIdPriorToSourceIfSet() { + public void testUsesSourcesDisplayAreaIdPriorToTaskIfSet() { final TestDisplayContent freeformDisplay = createNewDisplayContent( WINDOWING_MODE_FREEFORM); final TestDisplayContent fullscreenDisplay = createNewDisplayContent( @@ -211,7 +211,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { .setSource(source) .calculate()); - assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(), + assertEquals(freeformDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea); } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index bbb885eb0dd0..b88173d5c1f0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -54,6 +54,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.clearInvocations; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -1029,6 +1030,30 @@ public class WindowContainerTests extends WindowTestsBase { verify(win).clearFrozenInsetsState(); } + @Test + public void testAssignRelativeLayer() { + final WindowContainer container = new WindowContainer(mWm); + container.mSurfaceControl = mock(SurfaceControl.class); + final SurfaceAnimator surfaceAnimator = container.mSurfaceAnimator; + final SurfaceControl relativeParent = mock(SurfaceControl.class); + final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class); + spyOn(container); + spyOn(surfaceAnimator); + + // Trigger for first relative layer call. + container.assignRelativeLayer(t, relativeParent, 1 /* layer */); + verify(surfaceAnimator).setRelativeLayer(t, relativeParent, 1 /* layer */); + + // Not trigger for the same relative layer call. + clearInvocations(surfaceAnimator); + container.assignRelativeLayer(t, relativeParent, 1 /* layer */); + verify(surfaceAnimator, never()).setRelativeLayer(t, relativeParent, 1 /* layer */); + + // Trigger for the same relative layer call if forceUpdate=true + container.assignRelativeLayer(t, relativeParent, 1 /* layer */, true /* forceUpdate */); + verify(surfaceAnimator).setRelativeLayer(t, relativeParent, 1 /* layer */); + } + /* Used so we can gain access to some protected members of the {@link WindowContainer} class */ private static class TestWindowContainer extends WindowContainer<TestWindowContainer> { private final int mLayer; diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 9e419d4c3f3b..0510b9cb54e1 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -2212,6 +2212,7 @@ public class UsageStatsService extends SystemService implements @Override public void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId, @Nullable LocusId locusId, @NonNull IBinder appToken) { + if (locusId == null) return; Event event = new Event(LOCUS_ID_SET, SystemClock.elapsedRealtime()); event.mLocusId = locusId.getId(); event.mPackage = activity.getPackageName(); diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index 8fb3b4d530d9..85cd81bb4eb5 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -1023,7 +1023,8 @@ public class ProvisioningManager { * server) or other operator defined triggers. If RCS provisioning is already * completed at the time of callback registration, then this method shall be * invoked with the current configuration - * @param configXml The RCS configurationXML received OTA. + * @param configXml The RCS configuration XML received by OTA. It is defined + * by GSMA RCC.07. */ public void onConfigurationChanged(@NonNull byte[] configXml) {} @@ -1390,7 +1391,9 @@ public class ProvisioningManager { * provisioning is done using autoconfiguration, then these parameters shall be * sent in the HTTP get request to fetch the RCS provisioning. RCS client * configuration must be provided by the application before registering for the - * provisioning status events {@link #registerRcsProvisioningChangedCallback} + * provisioning status events {@link #registerRcsProvisioningCallback()} + * When the IMS/RCS service receives the RCS client configuration, it will detect + * the change in the configuration, and trigger the auto-configuration as needed. * @param rcc RCS client configuration {@link RcsClientConfiguration} */ @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) @@ -1457,7 +1460,7 @@ public class ProvisioningManager { * * @param executor The {@link Executor} to call the callback methods on * @param callback The rcs provisioning callback to be registered. - * @see #unregisterRcsProvisioningChangedCallback(RcsProvisioningCallback) + * @see #unregisterRcsProvisioningCallback(RcsProvisioningCallback) * @see SubscriptionManager.OnSubscriptionsChangedListener * @throws IllegalArgumentException if the subscription associated with this * callback is not active (SIM is not inserted, ESIM inactive) or the @@ -1473,12 +1476,12 @@ public class ProvisioningManager { */ @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) - public void registerRcsProvisioningChangedCallback( + public void registerRcsProvisioningCallback( @NonNull @CallbackExecutor Executor executor, @NonNull RcsProvisioningCallback callback) throws ImsException { callback.setExecutor(executor); try { - getITelephony().registerRcsProvisioningChangedCallback(mSubId, callback.getBinder()); + getITelephony().registerRcsProvisioningCallback(mSubId, callback.getBinder()); } catch (ServiceSpecificException e) { throw new ImsException(e.getMessage(), e.errorCode); } catch (RemoteException | IllegalStateException e) { @@ -1504,16 +1507,16 @@ public class ProvisioningManager { * * @param callback The existing {@link RcsProvisioningCallback} to be * removed. - * @see #registerRcsProvisioningChangedCallback - * @throws IllegalArgumentException if the subscription associated with this callback is - * invalid. + * @see #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback) + * @throws IllegalArgumentException if the subscription associated with + * this callback is invalid. */ @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) - public void unregisterRcsProvisioningChangedCallback( + public void unregisterRcsProvisioningCallback( @NonNull RcsProvisioningCallback callback) { try { - getITelephony().unregisterRcsProvisioningChangedCallback( + getITelephony().unregisterRcsProvisioningCallback( mSubId, callback.getBinder()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -1523,6 +1526,14 @@ public class ProvisioningManager { /** * Reconfiguration triggered by the RCS application. Most likely cause * is the 403 forbidden to a HTTP request. + * + * <p>When this api is called, the RCS configuration for the associated + * subscription will be removed, and the application which has registered + * {@link RcsProvisioningCallback} may expect to receive + * {@link RcsProvisioningCallback#onConfigurationReset}, then + * {@link RcsProvisioningCallback#onConfigurationChanged} when the new + * RCS configuration is received and notified by + * {@link #notifyRcsAutoConfigurationReceived} */ @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration() { diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 7e04baa5f82b..40b86966d0e8 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -2302,13 +2302,12 @@ interface ITelephony { /** * Register RCS provisioning callback. */ - void registerRcsProvisioningChangedCallback(int subId, - IRcsConfigCallback callback); + void registerRcsProvisioningCallback(int subId, IRcsConfigCallback callback); /** * Unregister RCS provisioning callback. */ - void unregisterRcsProvisioningChangedCallback(int subId, IRcsConfigCallback callback); + void unregisterRcsProvisioningCallback(int subId, IRcsConfigCallback callback); /** * trigger RCS reconfiguration. |