Merge "Ensure RuntimeExceptions are also caught properly."
diff --git a/apct-tests/perftests/core/OWNERS b/apct-tests/perftests/core/OWNERS
index 8fb057d..6abab6e 100644
--- a/apct-tests/perftests/core/OWNERS
+++ b/apct-tests/perftests/core/OWNERS
@@ -3,4 +3,12 @@
# Bug component: 568761
per-file /apct-tests/perftests/core/res/* = felkachang@google.com,zyy@google.com
+per-file /apct-tests/perftests/core/res/* = file:/core/java/android/content/om/OWNERS
+per-file /apct-tests/perftests/core/src/android/content/res/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/res/* = file:/core/java/android/content/res/OWNERS
+
+
+# Bug component: 568631
+per-file /apct-tests/perftests/core/src/android/content/om/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/om/* = file:/core/java/android/content/om/OWNERS
diff --git a/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java b/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
index e31162f..c00c8d5 100644
--- a/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
+++ b/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
@@ -39,6 +39,7 @@
private static final String NAMESPACE = "test@namespace";
private static final String SETTING_NAME1 = "test:setting1";
private static final String SETTING_NAME2 = "test-setting2";
+ private static final String UNSET_SETTING = "test_unset_setting";
private final ContentResolver mContentResolver;
@@ -93,6 +94,14 @@
}
@Test
+ public void testSettingsValueConsecutiveReadUnset() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Settings.Secure.getString(mContentResolver, UNSET_SETTING);
+ }
+ }
+
+ @Test
public void testSettingsNamespaceConsecutiveRead() {
final List<String> names = new ArrayList<>();
names.add(SETTING_NAME1);
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4caaa09..79a2659 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -79,6 +79,9 @@
import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -146,15 +149,17 @@
label="deep";
STATE_ACTIVE [
- label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon",
+ label="STATE_ACTIVE\nScreen on OR charging OR alarm going off soon\n"
+ + "OR active emergency call",
color=black,shape=diamond
]
STATE_INACTIVE [
- label="STATE_INACTIVE\nScreen off AND Not charging",color=black,shape=diamond
+ label="STATE_INACTIVE\nScreen off AND not charging AND no active emergency call",
+ color=black,shape=diamond
]
STATE_QUICK_DOZE_DELAY [
label="STATE_QUICK_DOZE_DELAY\n"
- + "Screen off AND Not charging\n"
+ + "Screen off AND not charging AND no active emergency call\n"
+ "Location, motion detection, and significant motion monitoring turned off",
color=black,shape=diamond
]
@@ -237,11 +242,12 @@
label="light"
LIGHT_STATE_ACTIVE [
- label="LIGHT_STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon",
+ label="LIGHT_STATE_ACTIVE\n"
+ + "Screen on OR charging OR alarm going off soon OR active emergency call",
color=black,shape=diamond
]
LIGHT_STATE_INACTIVE [
- label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging",
+ label="LIGHT_STATE_INACTIVE\nScreen off AND not charging AND no active emergency call",
color=black,shape=diamond
]
LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n",color=red,shape=box]
@@ -411,6 +417,7 @@
private static final int ACTIVE_REASON_FROM_BINDER_CALL = 5;
private static final int ACTIVE_REASON_FORCED = 6;
private static final int ACTIVE_REASON_ALARM = 7;
+ private static final int ACTIVE_REASON_EMERGENCY_CALL = 8;
@VisibleForTesting
static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1;
@VisibleForTesting
@@ -765,6 +772,8 @@
}
};
+ private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener();
+
/** Post stationary status only to this listener. */
private void postStationaryStatus(DeviceIdleInternal.StationaryListener listener) {
mHandler.obtainMessage(MSG_REPORT_STATIONARY_STATUS, listener).sendToTarget();
@@ -2323,6 +2332,39 @@
}
}
+ private class EmergencyCallListener extends TelephonyCallback implements
+ TelephonyCallback.OutgoingEmergencyCallListener,
+ TelephonyCallback.CallStateListener {
+ private volatile boolean mIsEmergencyCallActive;
+
+ @Override
+ public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber,
+ int subscriptionId) {
+ mIsEmergencyCallActive = true;
+ if (DEBUG) Slog.d(TAG, "onOutgoingEmergencyCall(): subId = " + subscriptionId);
+ synchronized (DeviceIdleController.this) {
+ mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+ becomeActiveLocked("emergency call", Process.myUid());
+ }
+ }
+
+ @Override
+ public void onCallStateChanged(int state) {
+ if (DEBUG) Slog.d(TAG, "onCallStateChanged(): state is " + state);
+ // An emergency call just finished
+ if (state == TelephonyManager.CALL_STATE_IDLE && mIsEmergencyCallActive) {
+ mIsEmergencyCallActive = false;
+ synchronized (DeviceIdleController.this) {
+ becomeInactiveIfAppropriateLocked();
+ }
+ }
+ }
+
+ boolean isEmergencyCallActive() {
+ return mIsEmergencyCallActive;
+ }
+ }
+
static class Injector {
private final Context mContext;
private ConnectivityManager mConnectivityManager;
@@ -2406,6 +2448,10 @@
return mContext.getSystemService(SensorManager.class);
}
+ TelephonyManager getTelephonyManager() {
+ return mContext.getSystemService(TelephonyManager.class);
+ }
+
ConstraintController getConstraintController(Handler handler,
DeviceIdleInternal localService) {
if (mContext.getPackageManager()
@@ -2634,6 +2680,9 @@
mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
+ mInjector.getTelephonyManager().registerTelephonyCallback(
+ JobSchedulerBackgroundThread.getExecutor(), mEmergencyCallListener);
+
passWhiteListsToForceAppStandbyTrackerLocked();
updateInteractivityLocked();
}
@@ -3435,6 +3484,7 @@
final boolean isScreenBlockingInactive =
mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
+ final boolean isEmergencyCallActive = mEmergencyCallListener.isEmergencyCallActive();
if (DEBUG) {
Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
+ " isScreenBlockingInactive=" + isScreenBlockingInactive
@@ -3442,10 +3492,11 @@
+ ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
+ ", mScreenLocked=" + mScreenLocked + ")"
+ " mCharging=" + mCharging
+ + " emergencyCall=" + isEmergencyCallActive
+ " mForceIdle=" + mForceIdle
);
}
- if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
+ if (!mForceIdle && (mCharging || isScreenBlockingInactive || isEmergencyCallActive)) {
return;
}
// Become inactive and determine if we will ultimately go idle.
@@ -3568,6 +3619,17 @@
}
EventLogTags.writeDeviceIdleLightStep();
+ if (mEmergencyCallListener.isEmergencyCallActive()) {
+ // The emergency call should have raised the state to ACTIVE and kept it there,
+ // so this method shouldn't be called. Don't proceed further.
+ Slog.wtf(TAG, "stepLightIdleStateLocked called when emergency call is active");
+ if (mLightState != LIGHT_STATE_ACTIVE) {
+ mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+ becomeActiveLocked("emergency", Process.myUid());
+ }
+ return;
+ }
+
switch (mLightState) {
case LIGHT_STATE_INACTIVE:
mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
@@ -3650,6 +3712,17 @@
if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
EventLogTags.writeDeviceIdleStep();
+ if (mEmergencyCallListener.isEmergencyCallActive()) {
+ // The emergency call should have raised the state to ACTIVE and kept it there,
+ // so this method shouldn't be called. Don't proceed further.
+ Slog.wtf(TAG, "stepIdleStateLocked called when emergency call is active");
+ if (mState != STATE_ACTIVE) {
+ mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+ becomeActiveLocked("emergency", Process.myUid());
+ }
+ return;
+ }
+
if (isUpcomingAlarmClock()) {
// Whoops, there is an upcoming alarm. We don't actually want to go idle.
if (mState != STATE_ACTIVE) {
@@ -3984,6 +4057,11 @@
}
}
+ @VisibleForTesting
+ boolean isEmergencyCallActive() {
+ return mEmergencyCallListener.isEmergencyCallActive();
+ }
+
@GuardedBy("this")
boolean isOpsInactiveLocked() {
return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
index a6a3aaf..6a4a52a 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -4,6 +4,7 @@
"name": "CtsUsageStatsTestCases",
"options": [
{"include-filter": "android.app.usage.cts.UsageStatsTest"},
+ {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
{"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
{"exclude-annotation": "androidx.test.filters.FlakyTest"},
{"exclude-annotation": "androidx.test.filters.MediumTest"},
@@ -19,18 +20,6 @@
]
}
],
- "presubmit-large": [
- {
- "name": "CtsUsageStatsTestCases",
- "options": [
- {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
- {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.MediumTest"},
- {"exclude-annotation": "androidx.test.filters.LargeTest"}
- ]
- }
- ],
"postsubmit": [
{
"name": "CtsUsageStatsTestCases"
diff --git a/core/api/current.txt b/core/api/current.txt
index ed246df..7930c01 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -375,7 +375,7 @@
public static final class R.attr {
ctor public R.attr();
field public static final int absListViewStyle = 16842858; // 0x101006a
- field public static final int accessibilityDataPrivate;
+ field public static final int accessibilityDataSensitive;
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
field public static final int accessibilityFlags = 16843652; // 0x1010384
@@ -7269,6 +7269,13 @@
method public void onSharedElementsReady();
}
+ public final class StartForegroundCalledOnStoppedServiceException extends java.lang.IllegalStateException implements android.os.Parcelable {
+ ctor public StartForegroundCalledOnStoppedServiceException(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.StartForegroundCalledOnStoppedServiceException> CREATOR;
+ }
+
public class StatusBarManager {
method @RequiresPermission(android.Manifest.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE) public boolean canLaunchCaptureContentActivityForNote(@NonNull android.app.Activity);
method public void requestAddTileService(@NonNull android.content.ComponentName, @NonNull CharSequence, @NonNull android.graphics.drawable.Icon, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
@@ -13587,12 +13594,11 @@
}
public static final class CreateCredentialRequest.Builder {
- ctor public CreateCredentialRequest.Builder(@NonNull android.os.Bundle, @NonNull android.os.Bundle);
+ ctor public CreateCredentialRequest.Builder(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle);
method @NonNull public android.credentials.CreateCredentialRequest build();
method @NonNull public android.credentials.CreateCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
method @NonNull public android.credentials.CreateCredentialRequest.Builder setIsSystemProviderRequired(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public android.credentials.CreateCredentialRequest.Builder setOrigin(@NonNull String);
- method @NonNull public android.credentials.CreateCredentialRequest.Builder setType(@NonNull String);
}
public final class CreateCredentialResponse implements android.os.Parcelable {
@@ -20382,7 +20388,7 @@
public final class GnssCapabilities implements android.os.Parcelable {
method public int describeContents();
method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
- method public boolean hasAccumulatedDeltaRange();
+ method public int hasAccumulatedDeltaRange();
method public boolean hasAntennaInfo();
method public boolean hasGeofencing();
method @Deprecated public boolean hasGnssAntennaInfo();
@@ -20408,8 +20414,10 @@
method public boolean hasSatellitePvt();
method public boolean hasScheduling();
method public boolean hasSingleShotFix();
- method public boolean isAccumulatedDeltaRangeCapabilityKnown();
method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
+ field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
+ field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
}
@@ -20417,9 +20425,8 @@
ctor public GnssCapabilities.Builder();
ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
method @NonNull public android.location.GnssCapabilities build();
- method @NonNull public android.location.GnssCapabilities.Builder clearIsAccumulatedDeltaRangeCapabilityKnown();
method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
@@ -33828,6 +33835,7 @@
method public android.os.Bundle getUserRestrictions();
method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(String);
+ method public boolean isAdminUser();
method public boolean isDemoUser();
method public static boolean isHeadlessSystemUserMode();
method public boolean isManagedProfile();
@@ -39855,6 +39863,7 @@
field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+ field public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6; // 0x6
field public static final int UI_TYPE_DIALOG = 3; // 0x3
field public static final int UI_TYPE_INLINE = 2; // 0x2
field public static final int UI_TYPE_MENU = 1; // 0x1
@@ -40531,7 +40540,7 @@
ctor public BeginCreateCredentialResponse();
method public int describeContents();
method @NonNull public java.util.List<android.service.credentials.CreateEntry> getCreateEntries();
- method @Nullable public android.service.credentials.CreateEntry getRemoteCreateEntry();
+ method @Nullable public android.service.credentials.RemoteEntry getRemoteCreateEntry();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialResponse> CREATOR;
}
@@ -40541,7 +40550,7 @@
method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder addCreateEntry(@NonNull android.service.credentials.CreateEntry);
method @NonNull public android.service.credentials.BeginCreateCredentialResponse build();
method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setCreateEntries(@NonNull java.util.List<android.service.credentials.CreateEntry>);
- method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.CreateEntry);
+ method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.RemoteEntry);
}
public class BeginGetCredentialOption implements android.os.Parcelable {
@@ -40576,7 +40585,7 @@
method @NonNull public java.util.List<android.service.credentials.Action> getActions();
method @NonNull public java.util.List<android.service.credentials.Action> getAuthenticationActions();
method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
- method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
+ method @Nullable public android.service.credentials.RemoteEntry getRemoteCredentialEntry();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginGetCredentialResponse> CREATOR;
}
@@ -40590,7 +40599,7 @@
method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setAuthenticationActions(@NonNull java.util.List<android.service.credentials.Action>);
method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
- method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
+ method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.RemoteEntry);
}
public final class CallingAppInfo implements android.os.Parcelable {
@@ -40660,14 +40669,22 @@
}
public final class GetCredentialRequest implements android.os.Parcelable {
- ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull android.credentials.CredentialOption);
+ ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull java.util.List<android.credentials.CredentialOption>);
method public int describeContents();
method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
- method @NonNull public android.credentials.CredentialOption getCredentialOption();
+ method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialRequest> CREATOR;
}
+ public class RemoteEntry implements android.os.Parcelable {
+ ctor public RemoteEntry(@NonNull android.app.slice.Slice);
+ method public int describeContents();
+ method @NonNull public android.app.slice.Slice getSlice();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.RemoteEntry> CREATOR;
+ }
+
}
package android.service.dreams {
@@ -52016,8 +52033,8 @@
method @Nullable public CharSequence getAccessibilityPaneTitle();
method @IdRes public int getAccessibilityTraversalAfter();
method @IdRes public int getAccessibilityTraversalBefore();
- method @NonNull public String getAllowedHandwritingDelegatePackageName();
- method @NonNull public String getAllowedHandwritingDelegatorPackageName();
+ method @Nullable public String getAllowedHandwritingDelegatePackageName();
+ method @Nullable public String getAllowedHandwritingDelegatorPackageName();
method public float getAlpha();
method public android.view.animation.Animation getAnimation();
method @Nullable public android.graphics.Matrix getAnimationMatrix();
@@ -52211,7 +52228,7 @@
method public void invalidate();
method public void invalidateDrawable(@NonNull android.graphics.drawable.Drawable);
method public void invalidateOutline();
- method public boolean isAccessibilityDataPrivate();
+ method public boolean isAccessibilityDataSensitive();
method public boolean isAccessibilityFocused();
method public boolean isAccessibilityHeading();
method public boolean isActivated();
@@ -52391,7 +52408,7 @@
method public void scrollTo(int, int);
method public void sendAccessibilityEvent(int);
method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
- method public void setAccessibilityDataPrivate(int);
+ method public void setAccessibilityDataSensitive(int);
method public void setAccessibilityDelegate(@Nullable android.view.View.AccessibilityDelegate);
method public void setAccessibilityHeading(boolean);
method public void setAccessibilityLiveRegion(int);
@@ -52400,8 +52417,8 @@
method public void setAccessibilityTraversalBefore(@IdRes int);
method public void setActivated(boolean);
method public void setAllowClickWhenDisabled(boolean);
- method public void setAllowedHandwritingDelegatePackage(@NonNull String);
- method public void setAllowedHandwritingDelegatorPackage(@NonNull String);
+ method public void setAllowedHandwritingDelegatePackage(@Nullable String);
+ method public void setAllowedHandwritingDelegatorPackage(@Nullable String);
method public void setAlpha(@FloatRange(from=0.0, to=1.0) float);
method public void setAnimation(android.view.animation.Animation);
method public void setAnimationMatrix(@Nullable android.graphics.Matrix);
@@ -52577,9 +52594,9 @@
method @CallSuper protected boolean verifyDrawable(@NonNull android.graphics.drawable.Drawable);
method @Deprecated public boolean willNotCacheDrawing();
method public boolean willNotDraw();
- field public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0; // 0x0
- field public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 2; // 0x2
- field public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 1; // 0x1
+ field public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0; // 0x0
+ field public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 2; // 0x2
+ field public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 1; // 0x1
field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
@@ -54049,11 +54066,11 @@
method public int getSpeechStateChangeTypes();
method public int getWindowChanges();
method public void initFromParcel(android.os.Parcel);
- method public boolean isAccessibilityDataPrivate();
+ method public boolean isAccessibilityDataSensitive();
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(int);
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain();
- method public void setAccessibilityDataPrivate(boolean);
+ method public void setAccessibilityDataSensitive(boolean);
method public void setAction(int);
method public void setContentChangeTypes(int);
method public void setEventTime(long);
@@ -54244,6 +54261,7 @@
method public int getWindowId();
method public boolean hasRequestInitialAccessibilityFocus();
method public boolean hasRequestTouchPassthrough();
+ method public boolean isAccessibilityDataSensitive();
method public boolean isAccessibilityFocused();
method public boolean isCheckable();
method public boolean isChecked();
@@ -54280,6 +54298,7 @@
method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
method public boolean removeChild(android.view.View);
method public boolean removeChild(android.view.View, int);
+ method public void setAccessibilityDataSensitive(boolean);
method public void setAccessibilityFocused(boolean);
method public void setAvailableExtraData(java.util.List<java.lang.String>);
method @Deprecated public void setBoundsInParent(android.graphics.Rect);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 53a55d8..29976c8 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1699,7 +1699,7 @@
method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupEnabled();
method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupServiceActive(android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.BACKUP) public String[] listAllTransports();
- method @NonNull public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
+ method public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver);
method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int);
method @Deprecated public int requestRestore(android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor);
@@ -3247,7 +3247,6 @@
method @NonNull public java.util.Set<android.content.ComponentName> getBlockedCrossTaskNavigations();
method public int getDefaultActivityPolicy();
method public int getDefaultNavigationPolicy();
- method public int getDefaultRecentsPolicy();
method public int getDevicePolicy(int);
method public int getLockState();
method @Nullable public String getName();
@@ -3264,8 +3263,8 @@
field public static final int NAVIGATION_POLICY_DEFAULT_ALLOWED = 0; // 0x0
field public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; // 0x1
field public static final int POLICY_TYPE_AUDIO = 1; // 0x1
+ field public static final int POLICY_TYPE_RECENTS = 2; // 0x2
field public static final int POLICY_TYPE_SENSORS = 0; // 0x0
- field public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1; // 0x1
}
public static final class VirtualDeviceParams.Builder {
@@ -3278,7 +3277,6 @@
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAudioRecordingSessionId(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedActivities(@NonNull java.util.Set<android.content.ComponentName>);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedCrossTaskNavigations(@NonNull java.util.Set<android.content.ComponentName>);
- method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDefaultRecentsPolicy(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDevicePolicy(int, int);
method @NonNull @RequiresPermission(value=android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY, conditional=true) public android.companion.virtual.VirtualDeviceParams.Builder setLockState(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setName(@NonNull String);
@@ -10002,48 +10000,80 @@
package android.net.wifi.sharedconnectivity.app {
- public final class DeviceInfo implements android.os.Parcelable {
+ public final class HotspotNetwork implements android.os.Parcelable {
method public int describeContents();
- method @IntRange(from=0, to=100) public int getBatteryPercentage();
- method @IntRange(from=0, to=3) public int getConnectionStrength();
- method @NonNull public String getDeviceName();
- method public int getDeviceType();
- method @NonNull public String getModelName();
+ method public long getDeviceId();
+ method public int getHostNetworkType();
+ method @Nullable public String getHotspotBssid();
+ method @NonNull public java.util.Set<java.lang.Integer> getHotspotSecurityTypes();
+ method @Nullable public String getHotspotSsid();
+ method @NonNull public String getNetworkName();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.DeviceInfo> CREATOR;
- field public static final int DEVICE_TYPE_LAPTOP = 3; // 0x3
- field public static final int DEVICE_TYPE_PHONE = 1; // 0x1
- field public static final int DEVICE_TYPE_TABLET = 2; // 0x2
- field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetwork> CREATOR;
+ field public static final int NETWORK_TYPE_CELLULAR = 1; // 0x1
+ field public static final int NETWORK_TYPE_ETHERNET = 3; // 0x3
+ field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int NETWORK_TYPE_WIFI = 2; // 0x2
}
- public static final class DeviceInfo.Builder {
- ctor public DeviceInfo.Builder();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceName(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceType(int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setModelName(@NonNull String);
+ public static final class HotspotNetwork.Builder {
+ ctor public HotspotNetwork.Builder();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder addHotspotSecurityType(int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork build();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setDeviceId(long);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHostNetworkType(int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotBssid(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotSsid(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkName(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkProviderInfo(@NonNull android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
+ }
+
+ public final class HotspotNetworkConnectionStatus implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.os.Bundle getExtras();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork getHotspotNetwork();
+ method public int getStatus();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
+ field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
+ field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
+ field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
+ field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
+ field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
+ field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
+ field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
+ field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
+ field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus> CREATOR;
+ }
+
+ public static final class HotspotNetworkConnectionStatus.Builder {
+ ctor public HotspotNetworkConnectionStatus.Builder();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus build();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setStatus(int);
}
public final class KnownNetwork implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
+ method @Nullable public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
method public int getNetworkSource();
method @NonNull public java.util.Set<java.lang.Integer> getSecurityTypes();
method @NonNull public String getSsid();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.KnownNetwork> CREATOR;
- field public static final int NETWORK_SOURCE_CLOUD_SELF = 1; // 0x1
- field public static final int NETWORK_SOURCE_NEARBY_SELF = 0; // 0x0
+ field public static final int NETWORK_SOURCE_CLOUD_SELF = 2; // 0x2
+ field public static final int NETWORK_SOURCE_NEARBY_SELF = 1; // 0x1
+ field public static final int NETWORK_SOURCE_UNKNOWN = 0; // 0x0
}
public static final class KnownNetwork.Builder {
ctor public KnownNetwork.Builder();
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder addSecurityType(int);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkProviderInfo(@Nullable android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkSource(int);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSsid(@NonNull String);
}
@@ -10068,29 +10098,56 @@
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.Builder setStatus(int);
}
+ public final class NetworkProviderInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0, to=100) public int getBatteryPercentage();
+ method @IntRange(from=0, to=3) public int getConnectionStrength();
+ method @NonNull public String getDeviceName();
+ method public int getDeviceType();
+ method @NonNull public String getModelName();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.NetworkProviderInfo> CREATOR;
+ field public static final int DEVICE_TYPE_AUTO = 5; // 0x5
+ field public static final int DEVICE_TYPE_LAPTOP = 3; // 0x3
+ field public static final int DEVICE_TYPE_PHONE = 1; // 0x1
+ field public static final int DEVICE_TYPE_TABLET = 2; // 0x2
+ field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int DEVICE_TYPE_WATCH = 4; // 0x4
+ }
+
+ public static final class NetworkProviderInfo.Builder {
+ ctor public NetworkProviderInfo.Builder(@NonNull String, @NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo build();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceName(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceType(int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setModelName(@NonNull String);
+ }
+
public interface SharedConnectivityClientCallback {
+ method public void onHotspotNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
+ method public void onHotspotNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
method public void onKnownNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
method public void onKnownNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
method public void onRegisterCallbackFailed(@NonNull Exception);
method public void onServiceConnected();
method public void onServiceDisconnected();
method public void onSharedConnectivitySettingsChanged(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
- method public void onTetherNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
- method public void onTetherNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
}
public class SharedConnectivityManager {
- method public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
- method public boolean connectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- method public boolean disconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- method public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
- method @Nullable public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
- method @NonNull public java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork> getKnownNetworks();
- method @Nullable public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState getSettingsState();
- method @Nullable public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus getTetherNetworkConnectionStatus();
- method @NonNull public java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork> getTetherNetworks();
- method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
- method public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean disconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork> getHotspotNetworks();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork> getKnownNetworks();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState getSettingsState();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
}
public final class SharedConnectivitySettingsState implements android.os.Parcelable {
@@ -10108,62 +10165,6 @@
method @NonNull public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.Builder setInstantTetherEnabled(boolean);
}
- public final class TetherNetwork implements android.os.Parcelable {
- method public int describeContents();
- method public long getDeviceId();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
- method @Nullable public String getHotspotBssid();
- method @NonNull public java.util.Set<java.lang.Integer> getHotspotSecurityTypes();
- method @Nullable public String getHotspotSsid();
- method @NonNull public String getNetworkName();
- method public int getNetworkType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetwork> CREATOR;
- field public static final int NETWORK_TYPE_CELLULAR = 1; // 0x1
- field public static final int NETWORK_TYPE_ETHERNET = 3; // 0x3
- field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
- field public static final int NETWORK_TYPE_WIFI = 2; // 0x2
- }
-
- public static final class TetherNetwork.Builder {
- ctor public TetherNetwork.Builder();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder addHotspotSecurityType(int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceId(long);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotBssid(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotSsid(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkName(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkType(int);
- }
-
- public final class TetherNetworkConnectionStatus implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.os.Bundle getExtras();
- method public int getStatus();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork getTetherNetwork();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
- field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
- field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
- field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
- field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
- field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
- field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
- field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
- field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
- field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus> CREATOR;
- }
-
- public static final class TetherNetworkConnectionStatus.Builder {
- ctor public TetherNetworkConnectionStatus.Builder();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setStatus(int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- }
-
}
package android.net.wifi.sharedconnectivity.service {
@@ -10171,15 +10172,15 @@
public abstract class SharedConnectivityService extends android.app.Service {
ctor public SharedConnectivityService();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public abstract void onConnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
method public abstract void onConnectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
- method public abstract void onConnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- method public abstract void onDisconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
+ method public abstract void onDisconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
method public abstract void onForgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+ method public final void setHotspotNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
method public final void setKnownNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
method public final void setSettingsState(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
- method public final void setTetherNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
+ method public final void updateHotspotNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
method public final void updateKnownNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
- method public final void updateTetherNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
}
}
@@ -10960,7 +10961,6 @@
method @NonNull @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.MANAGE_USERS"}) public java.util.Set<android.os.UserHandle> getVisibleUsers();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean hasRestrictedProfiles();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean hasUserRestrictionForUser(@NonNull String, @NonNull android.os.UserHandle);
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isAdminUser();
method public boolean isCloneProfile();
method @Deprecated public boolean isCredentialSharableWithParent();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isGuestUser();
@@ -13264,22 +13264,18 @@
public abstract class VisualQueryDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
ctor public VisualQueryDetectionService();
+ method public final void finishQuery() throws java.lang.IllegalStateException;
+ method public final void gainedAttention();
+ method public final void lostAttention();
method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
- method public void onStartDetection(@NonNull android.service.voice.VisualQueryDetectionService.Callback);
+ method public void onStartDetection();
method public void onStopDetection();
method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
+ method public final void rejectQuery() throws java.lang.IllegalStateException;
+ method public final void streamQuery(@NonNull String) throws java.lang.IllegalStateException;
field public static final String SERVICE_INTERFACE = "android.service.voice.VisualQueryDetectionService";
}
- public static final class VisualQueryDetectionService.Callback {
- ctor public VisualQueryDetectionService.Callback();
- method public void onAttentionGained();
- method public void onAttentionLost();
- method public void onQueryDetected(@NonNull String) throws java.lang.IllegalStateException;
- method public void onQueryFinished() throws java.lang.IllegalStateException;
- method public void onQueryRejected() throws java.lang.IllegalStateException;
- }
-
public final class VisualQueryDetectionServiceFailure extends android.service.voice.DetectorFailure {
method public int getErrorCode();
method public int getSuggestedAction();
@@ -13794,7 +13790,7 @@
field public static final String EXTRA_CALL_HAS_IN_BAND_RINGTONE = "android.telecom.extra.CALL_HAS_IN_BAND_RINGTONE";
field public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
field public static final String EXTRA_CALL_TECHNOLOGY_TYPE = "android.telecom.extra.CALL_TECHNOLOGY_TYPE";
- field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
+ field @Deprecated public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
field public static final String EXTRA_CURRENT_TTY_MODE = "android.telecom.extra.CURRENT_TTY_MODE";
field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6e6ec44..2f8d0b5 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -3343,6 +3343,7 @@
field public static final int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1; // 0x1
field public static final int DISPLAY_IME_POLICY_HIDE = 2; // 0x2
field public static final int DISPLAY_IME_POLICY_LOCAL = 0; // 0x0
+ field public static final int LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP = 600; // 0x258
}
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
@@ -3773,6 +3774,7 @@
public final class TaskFragmentInfo implements android.os.Parcelable {
method public boolean equalsForTaskFragmentOrganizer(@Nullable android.window.TaskFragmentInfo);
method @NonNull public java.util.List<android.os.IBinder> getActivities();
+ method @NonNull public java.util.List<android.os.IBinder> getActivitiesRequestedInTaskFragment();
method @NonNull public android.content.res.Configuration getConfiguration();
method @NonNull public android.os.IBinder getFragmentToken();
method @NonNull public android.graphics.Point getPositionInParent();
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 44327af..b35e87b 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -598,6 +598,23 @@
}
/**
+ * Returns {@code true} if the activity was explicitly requested to be launched in the
+ * TaskFragment.
+ *
+ * @param activityToken The token of the Activity.
+ * @param taskFragmentToken The token of the TaskFragment.
+ */
+ public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
+ IBinder taskFragmentToken) {
+ try {
+ return getActivityClientController().isRequestedToLaunchInTaskFragment(activityToken,
+ taskFragmentToken);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Shows or hides a Camera app compat toggle for stretched issues with the requested state.
*
* @param token The token for the window that needs a control.
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ba36d93..87fe215 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -630,7 +630,7 @@
PROCESS_CAPABILITY_FOREGROUND_LOCATION,
PROCESS_CAPABILITY_FOREGROUND_CAMERA,
PROCESS_CAPABILITY_FOREGROUND_MICROPHONE,
- PROCESS_CAPABILITY_NETWORK,
+ PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
PROCESS_CAPABILITY_BFSL,
})
@Retention(RetentionPolicy.SOURCE)
@@ -791,7 +791,7 @@
public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
| PROCESS_CAPABILITY_FOREGROUND_CAMERA
| PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- | PROCESS_CAPABILITY_NETWORK
+ | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
| PROCESS_CAPABILITY_BFSL;
/**
@@ -810,7 +810,7 @@
pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
- pw.print((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+ pw.print((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
}
@@ -819,7 +819,7 @@
sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
- sb.append((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+ sb.append((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index b9f38d3..d810f05 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -968,14 +968,6 @@
public abstract void stopForegroundServiceDelegate(@NonNull ServiceConnection connection);
/**
- * Called by PowerManager. Return whether a given procstate is allowed to hold
- * wake locks in deep doze. Because it's called with the power manager lock held, we can't
- * hold AM locks in it.
- * @hide
- */
- public abstract boolean canHoldWakeLocksInDeepDoze(int uid, int procstate);
-
- /**
* Same as {@link android.app.IActivityManager#startProfile(int userId)}, but it would succeed
* even if the profile is disabled - it should only be called by
* {@link com.android.server.devicepolicy.DevicePolicyManagerService} when starting a profile
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 50275ab..dfdfd0e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -558,9 +558,6 @@
boolean hideForNow;
Configuration createdConfig;
Configuration overrideConfig;
- // TODO(b/263402465): pass deviceId directly in LaunchActivityItem#execute
- // The deviceId assigned by the server when this activity was first started.
- int mDeviceId;
// Used for consolidating configs before sending on to Activity.
private Configuration tmpConfig = new Configuration();
// Callback used for updating activity override config and camera compat control state.
@@ -623,7 +620,7 @@
}
public ActivityClientRecord(IBinder token, Intent intent, int ident,
- ActivityInfo info, Configuration overrideConfig, int deviceId,
+ ActivityInfo info, Configuration overrideConfig,
String referrer, IVoiceInteractor voiceInteractor, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
@@ -645,7 +642,6 @@
this.isForward = isForward;
this.profilerInfo = profilerInfo;
this.overrideConfig = overrideConfig;
- this.mDeviceId = deviceId;
this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo);
mActivityOptions = activityOptions;
mLaunchedFromBubble = launchedFromBubble;
@@ -3876,7 +3872,7 @@
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions, Intent customIntent) {
+ PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -3889,7 +3885,7 @@
// Make sure we are running with the most recent config.
mConfigurationController.handleConfigurationChanged(null, null);
- updateDeviceIdForNonUIContexts(r.mDeviceId);
+ updateDeviceIdForNonUIContexts(deviceId);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
@@ -5946,7 +5942,7 @@
r.startsNotResumed = startsNotResumed;
r.overrideConfig = overrideConfig;
- handleLaunchActivity(r, pendingActions, customIntent);
+ handleLaunchActivity(r, pendingActions, mLastReportedDeviceId, customIntent);
}
@Override
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a99815c..6301ad7 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -556,12 +556,7 @@
@Override
public ActivityInfo getActivityInfo(ComponentName className, ComponentInfoFlags flags)
throws NameNotFoundException {
- return getActivityInfoAsUser(className, flags, getUserId());
- }
-
- @Override
- public ActivityInfo getActivityInfoAsUser(ComponentName className,
- ComponentInfoFlags flags, @UserIdInt int userId) throws NameNotFoundException {
+ final int userId = getUserId();
try {
ActivityInfo ai = mPM.getActivityInfo(className,
updateFlagsForComponent(flags.getValue(), userId, null), userId);
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 6bb38e7..49fb794 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -188,7 +188,7 @@
/** Perform activity launch. */
public abstract Activity handleLaunchActivity(@NonNull ActivityClientRecord r,
- PendingTransactionActions pendingActions, Intent customIntent);
+ PendingTransactionActions pendingActions, int deviceId, Intent customIntent);
/** Perform activity start. */
public abstract void handleStartActivity(@NonNull ActivityClientRecord r,
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e3ec493..4713a31 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2814,7 +2814,7 @@
public @NonNull Context createDeviceContext(int deviceId) {
if (deviceId != Context.DEVICE_ID_DEFAULT) {
VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
- if (!vdm.isValidVirtualDeviceId(deviceId)) {
+ if (vdm == null || !vdm.isValidVirtualDeviceId(deviceId)) {
throw new IllegalArgumentException(
"Not a valid ID of the default device or any virtual device: " + deviceId);
}
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index 5136b20..a3c5e1c 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -181,4 +181,14 @@
* that started the task.
*/
void enableTaskLocaleOverride(in IBinder token);
+
+ /**
+ * Return {@code true} if the activity was explicitly requested to be launched in the
+ * TaskFragment.
+ *
+ * @param activityToken The token of the Activity.
+ * @param taskFragmentToken The token of the TaskFragment.
+ */
+ boolean isRequestedToLaunchInTaskFragment(in IBinder activityToken,
+ in IBinder taskFragmentToken);
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 5cad1ae..ac92811 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -93,7 +93,7 @@
private static final String TAG = "Instrumentation";
- private static final long CONNECT_TIMEOUT_MILLIS = 5000;
+ private static final long CONNECT_TIMEOUT_MILLIS = 60_000;
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java
new file mode 100644
index 0000000..55885a6
--- /dev/null
+++ b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when {@link Service#startForeground} is called on a service that's not
+ * actually started.
+ */
+public final class StartForegroundCalledOnStoppedServiceException
+ extends IllegalStateException implements Parcelable {
+ /**
+ * Constructor.
+ */
+ public StartForegroundCalledOnStoppedServiceException(@NonNull String message) {
+ super(message);
+ }
+
+ StartForegroundCalledOnStoppedServiceException(@NonNull Parcel source) {
+ super(source.readString());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(getMessage());
+ }
+
+ public static final @NonNull Creator<StartForegroundCalledOnStoppedServiceException>
+ CREATOR = new Creator<StartForegroundCalledOnStoppedServiceException>() {
+ @NonNull
+ public StartForegroundCalledOnStoppedServiceException createFromParcel(
+ Parcel source) {
+ return new StartForegroundCalledOnStoppedServiceException(source);
+ }
+
+ @NonNull
+ public StartForegroundCalledOnStoppedServiceException[] newArray(int size) {
+ return new StartForegroundCalledOnStoppedServiceException[size];
+ }
+ };
+}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6d80a44..dbba0c6 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -509,7 +509,7 @@
new ServiceFetcher<InputManager>() {
@Override
public InputManager getService(ContextImpl ctx) {
- return InputManager.getInstance(ctx);
+ return InputManager.getInstance(ctx.getOuterContext());
}});
registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
@@ -877,6 +877,10 @@
@Override
public VirtualDeviceManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
+ if (!ctx.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
+ return null;
+ }
IVirtualDeviceManager service = IVirtualDeviceManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.VIRTUAL_DEVICE_SERVICE));
return new VirtualDeviceManager(service, ctx.getOuterContext());
@@ -1648,6 +1652,7 @@
case Context.ETHERNET_SERVICE:
case Context.CONTEXTHUB_SERVICE:
case Context.VIRTUALIZATION_SERVICE:
+ case Context.VIRTUAL_DEVICE_SERVICE:
return null;
}
Slog.wtf(TAG, "Manager wrapper not available: " + name);
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 5a2f261..303ada0 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -453,6 +453,7 @@
&& Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays)
&& Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
&& getWindowingMode() == that.getWindowingMode()
+ && configuration.uiMode == that.configuration.uiMode
&& Objects.equals(taskDescription, that.taskDescription)
&& isFocused == that.isFocused
&& isVisible == that.isVisible
@@ -481,6 +482,7 @@
.equals(that.configuration.windowConfiguration.getBounds()))
&& (!hasCompatUI() || configuration.getLayoutDirection()
== that.configuration.getLayoutDirection())
+ && (!hasCompatUI() || configuration.uiMode == that.configuration.uiMode)
&& (!hasCompatUI() || isVisible == that.isVisible);
}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index e750f49..5848521 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -1091,7 +1091,6 @@
*
* @hide
*/
- @NonNull
@SystemApi
public void reportDelayedRestoreResult(@NonNull BackupRestoreEventLogger logger) {
checkServiceBinder();
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index f56c8c3..dcac59c 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -656,11 +656,14 @@
}
/**
- * Ask the transport for a {@link IBackupManagerMonitor} instance which will be used by the
+ * Ask the transport for a {@link BackupManagerMonitor} instance which will be used by the
* framework to report logging events back to the transport.
*
* <p>Backups requested from outside the framework may pass in a monitor with the request,
* however backups initiated by the framework will call this method to retrieve one.
+ *
+ * @return {@link BackupManagerMonitor} or {@code null} if the transport implementation does not
+ * wish to receive the logging events.
*/
@Nullable
public BackupManagerMonitor getBackupManagerMonitor() {
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 3d0aa25..5833f1b 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -96,11 +96,11 @@
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
- mOverrideConfig, mDeviceId, mReferrer, mVoiceInteractor, mState, mPersistentState,
+ mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
mTaskFragmentToken);
- client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
+ client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index c8f7d10..bfab61f 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -32,6 +32,7 @@
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
+import android.content.Context;
import android.os.IBinder;
import android.util.IntArray;
import android.util.Slog;
@@ -218,7 +219,7 @@
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
- null /* customIntent */);
+ Context.DEVICE_ID_INVALID, null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions,
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index 9f3b601..3a60a69 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -140,7 +140,8 @@
* a given policy type.
* @hide
*/
- @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO})
+ @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO,
+ POLICY_TYPE_RECENTS})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface PolicyType {}
@@ -169,22 +170,21 @@
* <li>{@link #DEVICE_POLICY_CUSTOM}: audio framework will assign device specific session
* ids to players and recorders constructed within device context. The session ids are
* used to re-route corresponding audio streams to VirtualAudioDevice.
- * <ul/>
+ * </ul>
*/
public static final int POLICY_TYPE_AUDIO = 1;
- /** @hide */
- @IntDef(flag = true, prefix = "RECENTS_POLICY_",
- value = {RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS})
- @Retention(RetentionPolicy.SOURCE)
- @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
- public @interface RecentsPolicy {}
-
/**
- * If set, activities launched on this virtual device are allowed to appear in the host device
- * of the recently launched activities list.
+ * Tells the activity manager how to handle recents entries for activities run on this device.
+ *
+ * <ul>
+ * <li>{@link #DEVICE_POLICY_DEFAULT}: Activities launched on VirtualDisplays owned by this
+ * device will appear in the host device recents.
+ * <li>{@link #DEVICE_POLICY_CUSTOM}: Activities launched on VirtualDisplays owned by this
+ * * device will not appear in recents.
+ * </ul>
*/
- public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1 << 0;
+ public static final int POLICY_TYPE_RECENTS = 2;
private final int mLockState;
@NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
@@ -201,8 +201,6 @@
@NonNull private final SparseIntArray mDevicePolicies;
@NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs;
@Nullable private final IVirtualSensorCallback mVirtualSensorCallback;
- @RecentsPolicy
- private final int mDefaultRecentsPolicy;
private final int mAudioPlaybackSessionId;
private final int mAudioRecordingSessionId;
@@ -219,7 +217,6 @@
@NonNull SparseIntArray devicePolicies,
@NonNull List<VirtualSensorConfig> virtualSensorConfigs,
@Nullable IVirtualSensorCallback virtualSensorCallback,
- @RecentsPolicy int defaultRecentsPolicy,
int audioPlaybackSessionId,
int audioRecordingSessionId) {
mLockState = lockState;
@@ -237,10 +234,8 @@
mDevicePolicies = Objects.requireNonNull(devicePolicies);
mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
mVirtualSensorCallback = virtualSensorCallback;
- mDefaultRecentsPolicy = defaultRecentsPolicy;
mAudioPlaybackSessionId = audioPlaybackSessionId;
mAudioRecordingSessionId = audioRecordingSessionId;
-
}
@SuppressWarnings("unchecked")
@@ -259,7 +254,6 @@
parcel.readTypedList(mVirtualSensorConfigs, VirtualSensorConfig.CREATOR);
mVirtualSensorCallback =
IVirtualSensorCallback.Stub.asInterface(parcel.readStrongBinder());
- mDefaultRecentsPolicy = parcel.readInt();
mAudioPlaybackSessionId = parcel.readInt();
mAudioRecordingSessionId = parcel.readInt();
}
@@ -396,16 +390,6 @@
}
/**
- * Returns the policy of how to handle activities in recents.
- *
- * @see RecentsPolicy
- */
- @RecentsPolicy
- public int getDefaultRecentsPolicy() {
- return mDefaultRecentsPolicy;
- }
-
- /**
* Returns device-specific audio session id for playback.
*
* @see Builder#setAudioPlaybackSessionId(int)
@@ -443,7 +427,6 @@
dest.writeTypedList(mVirtualSensorConfigs);
dest.writeStrongBinder(
mVirtualSensorCallback != null ? mVirtualSensorCallback.asBinder() : null);
- dest.writeInt(mDefaultRecentsPolicy);
dest.writeInt(mAudioPlaybackSessionId);
dest.writeInt(mAudioRecordingSessionId);
}
@@ -478,7 +461,6 @@
&& Objects.equals(mBlockedActivities, that.mBlockedActivities)
&& mDefaultActivityPolicy == that.mDefaultActivityPolicy
&& Objects.equals(mName, that.mName)
- && mDefaultRecentsPolicy == that.mDefaultRecentsPolicy
&& mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
&& mAudioRecordingSessionId == that.mAudioRecordingSessionId;
}
@@ -489,7 +471,7 @@
mLockState, mUsersWithMatchingAccounts, mAllowedCrossTaskNavigations,
mBlockedCrossTaskNavigations, mDefaultNavigationPolicy, mAllowedActivities,
mBlockedActivities, mDefaultActivityPolicy, mName, mDevicePolicies,
- mDefaultRecentsPolicy, mAudioPlaybackSessionId, mAudioRecordingSessionId);
+ mAudioPlaybackSessionId, mAudioRecordingSessionId);
for (int i = 0; i < mDevicePolicies.size(); i++) {
hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -511,7 +493,6 @@
+ " mDefaultActivityPolicy=" + mDefaultActivityPolicy
+ " mName=" + mName
+ " mDevicePolicies=" + mDevicePolicies
- + " mDefaultRecentsPolicy=" + mDefaultRecentsPolicy
+ " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
+ " mAudioRecordingSessionId=" + mAudioRecordingSessionId
+ ")";
@@ -548,7 +529,6 @@
private boolean mDefaultActivityPolicyConfigured = false;
@Nullable private String mName;
@NonNull private SparseIntArray mDevicePolicies = new SparseIntArray();
- private int mDefaultRecentsPolicy;
private int mAudioPlaybackSessionId = AUDIO_SESSION_ID_GENERATE;
private int mAudioRecordingSessionId = AUDIO_SESSION_ID_GENERATE;
@@ -821,17 +801,6 @@
}
/**
- * Sets the policy to indicate how activities are handled in recents.
- *
- * @param defaultRecentsPolicy A policy specifying how to handle activities in recents.
- */
- @NonNull
- public Builder setDefaultRecentsPolicy(@RecentsPolicy int defaultRecentsPolicy) {
- mDefaultRecentsPolicy = defaultRecentsPolicy;
- return this;
- }
-
- /**
* Sets audio playback session id specific for this virtual device.
*
* <p>Audio players constructed within context associated with this virtual device
@@ -933,7 +902,6 @@
mDevicePolicies,
mVirtualSensorConfigs,
mVirtualSensorCallback,
- mDefaultRecentsPolicy,
mAudioPlaybackSessionId,
mAudioRecordingSessionId);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 658702f..a412560 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -528,7 +528,7 @@
/**
* Flag for {@link #bindService}: allow the process hosting the target service to gain
- * {@link ActivityManager#PROCESS_CAPABILITY_NETWORK}, which allows it be able
+ * {@link ActivityManager#PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK}, which allows it be able
* to access network regardless of any power saving restrictions.
*
* @hide
@@ -5703,6 +5703,9 @@
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.companion.virtual.VirtualDeviceManager} for managing virtual devices.
*
+ * On devices without {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP}
+ * system feature the {@link #getSystemService(String)} will return {@code null}.
+ *
* @see #getSystemService(String)
* @see android.companion.virtual.VirtualDeviceManager
*/
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index bd3cf5f..afc2285 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -20,9 +20,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
@@ -185,28 +182,6 @@
private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
/**
- * An intent with action set as null used to always pass the action test during intent
- * filter matching. This causes a lot of confusion and unexpected intent matches.
- * Null action intents should be blocked when either the intent sender or receiver
- * application targets U or higher.
- *
- * mBlockNullAction indicates whether the intent filter owner (intent receiver) is
- * targeting U+. This value will be properly set by package manager when IntentFilters are
- * passed to an application, so that when an application is trying to perform intent filter
- * matching locally, the correct matching algorithm will be chosen.
- *
- * When an IntentFilter is sent to system server (e.g. for registering runtime receivers),
- * the value set in mBlockNullAction will be ignored and overwritten with the correct
- * value evaluated based on the Binder calling identity. This makes sure that the
- * security enforcement cannot be bypassed by crafting a malicious IntentFilter.
- *
- * @hide
- */
- @ChangeId
- @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
- public static final long BLOCK_NULL_ACTION_INTENTS = 264497795;
-
- /**
* The filter {@link #setPriority} value at which system high-priority
* receivers are placed; that is, receivers that should execute before
* application code. Applications should never use filters with this or
@@ -2301,7 +2276,6 @@
String type = resolve ? intent.resolveType(resolver) : intent.getType();
return match(intent.getAction(), type, intent.getScheme(),
intent.getData(), intent.getCategories(), logTag,
- CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
false /* supportWildcards */, null /* ignoreActions */,
intent.getExtras());
}
@@ -2354,7 +2328,6 @@
Uri data, Set<String> categories, String logTag, boolean supportWildcards,
@Nullable Collection<String> ignoreActions) {
return match(action, type, scheme, data, categories, logTag, supportWildcards,
- CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
ignoreActions, null /* extras */);
}
@@ -2366,10 +2339,8 @@
*/
public final int match(String action, String type, String scheme,
Uri data, Set<String> categories, String logTag, boolean supportWildcards,
- boolean blockNullAction, @Nullable Collection<String> ignoreActions,
- @Nullable Bundle extras) {
- if ((action == null && blockNullAction)
- || !matchAction(action, supportWildcards, ignoreActions)) {
+ @Nullable Collection<String> ignoreActions, @Nullable Bundle extras) {
+ if (action != null && !matchAction(action, supportWildcards, ignoreActions)) {
if (false) Log.v(
logTag, "No matching action " + action + " for " + this);
return NO_MATCH_ACTION;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d927c5e..9388823 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5720,17 +5720,6 @@
}
/**
- * @hide
- */
- @NonNull
- public ActivityInfo getActivityInfoAsUser(@NonNull ComponentName component,
- @NonNull ComponentInfoFlags flags, @UserIdInt int userId)
- throws NameNotFoundException {
- throw new UnsupportedOperationException(
- "getActivityInfoAsUser not implemented in subclass");
- }
-
- /**
* Retrieve all of the information we know about a particular receiver
* class.
*
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 45e0efb..b601275 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -28,7 +28,13 @@
"path": "cts/hostsidetests/os/test_mappings/packagemanager"
},
{
+ "path": "cts/hostsidetests/appsearch"
+ },
+ {
"path": "system/apex/tests"
+ },
+ {
+ "path": "cts/tests/tests/content/pm/SecureFrp"
}
],
"presubmit": [
@@ -43,6 +49,12 @@
"name": "ApkVerityTest"
},
{
+ "name": "CtsSilentUpdateHostTestCases"
+ },
+ {
+ "name": "CtsSuspendAppsTestCases"
+ },
+ {
"name": "CtsAppFgsTestCases",
"file_patterns": ["(/|^)ServiceInfo[^/]*"],
"options": [
@@ -108,50 +120,6 @@
]
},
{
- "name": "CtsAppSearchHostTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
- "name": "CtsSilentUpdateHostTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
- "name": "CtsSuspendAppsTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
- "name": "CtsSecureFrpInstallTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
"name": "CtsSuspendAppsPermissionTestCases",
"options": [
{
diff --git a/core/java/android/content/pm/UserPackage.java b/core/java/android/content/pm/UserPackage.java
index 7ca92c3..c35e678 100644
--- a/core/java/android/content/pm/UserPackage.java
+++ b/core/java/android/content/pm/UserPackage.java
@@ -18,14 +18,16 @@
import android.annotation.NonNull;
import android.annotation.UserIdInt;
-import android.os.Process;
-import android.os.UserHandle;
import android.util.SparseArrayMap;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import libcore.util.EmptyArray;
+
import java.util.Objects;
+import java.util.Random;
/**
* POJO to represent a package for a specific user ID.
@@ -34,6 +36,16 @@
*/
public final class UserPackage {
private static final boolean ENABLE_CACHING = true;
+ /**
+ * The maximum number of entries to keep in the cache per user ID.
+ * The value should ideally be high enough to cover all packages on an end-user device,
+ * but low enough that stale or invalid packages would eventually (probably) get removed.
+ * This should benefit components that loop through all packages on a device and use this class,
+ * since being able to cache the objects for all packages on the device
+ * means we don't have to keep recreating the objects.
+ */
+ @VisibleForTesting
+ static final int MAX_NUM_CACHED_ENTRIES_PER_USER = 1000;
@UserIdInt
public final int userId;
@@ -43,11 +55,13 @@
@GuardedBy("sCacheLock")
private static final SparseArrayMap<String, UserPackage> sCache = new SparseArrayMap<>();
- private static final class NoPreloadHolder {
- /** Set of userIDs to cache objects for. */
- @GuardedBy("sCacheLock")
- private static int[] sUserIds = new int[]{UserHandle.getUserId(Process.myUid())};
- }
+ /**
+ * Set of userIDs to cache objects for. We start off with an empty set, so there's no caching
+ * by default. The system will override with a valid set of userIDs in its process so that
+ * caching becomes active in the system process.
+ */
+ @GuardedBy("sCacheLock")
+ private static int[] sUserIds = EmptyArray.INT;
private UserPackage(int userId, String packageName) {
this.userId = userId;
@@ -87,13 +101,14 @@
}
synchronized (sCacheLock) {
- if (!ArrayUtils.contains(NoPreloadHolder.sUserIds, userId)) {
+ if (!ArrayUtils.contains(sUserIds, userId)) {
// Don't cache objects for invalid userIds.
return new UserPackage(userId, packageName);
}
UserPackage up = sCache.get(userId, packageName);
if (up == null) {
+ maybePurgeRandomEntriesLocked(userId);
packageName = packageName.intern();
up = new UserPackage(userId, packageName);
sCache.add(userId, packageName, up);
@@ -121,7 +136,7 @@
userIds = userIds.clone();
synchronized (sCacheLock) {
- NoPreloadHolder.sUserIds = userIds;
+ sUserIds = userIds;
for (int u = sCache.numMaps() - 1; u >= 0; --u) {
final int userId = sCache.keyAt(u);
@@ -131,4 +146,35 @@
}
}
}
+
+ @VisibleForTesting
+ public static int numEntriesForUser(int userId) {
+ synchronized (sCacheLock) {
+ return sCache.numElementsForKey(userId);
+ }
+ }
+
+ /** Purge a random set of entries if the cache size is too large. */
+ @GuardedBy("sCacheLock")
+ private static void maybePurgeRandomEntriesLocked(int userId) {
+ final int uIdx = sCache.indexOfKey(userId);
+ if (uIdx < 0) {
+ return;
+ }
+ int numCached = sCache.numElementsForKeyAt(uIdx);
+ if (numCached < MAX_NUM_CACHED_ENTRIES_PER_USER) {
+ return;
+ }
+ // Purge a random set of 1% of cached elements for the userId. We don't want to use a
+ // deterministic system of purging because that may cause us to repeatedly remove elements
+ // that are frequently added and queried more than others. Choosing a random set
+ // means we will probably eventually remove less useful elements.
+ // An LRU cache is too expensive for this commonly used utility class.
+ final Random rand = new Random();
+ final int numToPurge = Math.max(1, MAX_NUM_CACHED_ENTRIES_PER_USER / 100);
+ for (int i = 0; i < numToPurge && numCached > 0; ++i) {
+ final int removeIdx = rand.nextInt(numCached--);
+ sCache.deleteAt(uIdx, removeIdx);
+ }
+ }
}
diff --git a/core/java/android/credentials/CreateCredentialRequest.java b/core/java/android/credentials/CreateCredentialRequest.java
index c89a5c6..fc3dc79 100644
--- a/core/java/android/credentials/CreateCredentialRequest.java
+++ b/core/java/android/credentials/CreateCredentialRequest.java
@@ -260,11 +260,17 @@
private String mOrigin;
/**
+ * @param type the type of the credential to be stored
* @param credentialData the full credential creation request data
* @param candidateQueryData the partial request data that will be sent to the provider
* during the initial creation candidate query stage
*/
- public Builder(@NonNull Bundle credentialData, @NonNull Bundle candidateQueryData) {
+ public Builder(
+ @NonNull String type,
+ @NonNull Bundle credentialData,
+ @NonNull Bundle candidateQueryData) {
+ mType = Preconditions.checkStringNotEmpty(type,
+ "type must not be null or empty");
mCredentialData = requireNonNull(credentialData,
"credentialData must not be null");
mCandidateQueryData = requireNonNull(candidateQueryData,
@@ -291,16 +297,6 @@
}
/**
- * Sets the requested credential type.
- */
- @SuppressLint("MissingGetterMatchingBuilder")
- @NonNull
- public CreateCredentialRequest.Builder setType(@NonNull String type) {
- mType = type;
- return this;
- }
-
- /**
* Sets whether the request must only be fulfilled by a system provider.
* This defaults to false
*/
diff --git a/core/java/android/credentials/GetCredentialRequest.java b/core/java/android/credentials/GetCredentialRequest.java
index 951cbe4..c58d2dc 100644
--- a/core/java/android/credentials/GetCredentialRequest.java
+++ b/core/java/android/credentials/GetCredentialRequest.java
@@ -149,7 +149,6 @@
mCredentialOptions = credentialOptions;
AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
-
Bundle data = in.readBundle();
mData = data;
AnnotationValidations.validate(NonNull.class, null, mData);
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index ddbfb9e..889a43c 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -40,7 +40,7 @@
* HardwareBuffer wraps a native <code>AHardwareBuffer</code> object, which is a low-level object
* representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing
* buffers across different application processes. In particular, HardwareBuffers may be mappable
- * to memory accessibly to various hardware systems, such as the GPU, a sensor or context hub, or
+ * to memory accessible to various hardware systems, such as the GPU, a sensor or context hub, or
* other auxiliary processing units.
*
* For more information, see the NDK documentation for <code>AHardwareBuffer</code>.
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a33cd97..490589f 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -48,8 +48,6 @@
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemClock;
import android.os.VibrationEffect;
import android.os.Vibrator;
@@ -305,8 +303,11 @@
private static String sVelocityTrackerStrategy;
- private InputManager(IInputManager im) {
- mIm = im;
+ private InputManagerGlobal mGlobal;
+
+ private InputManager() {
+ mGlobal = InputManagerGlobal.getInstance();
+ mIm = mGlobal.getInputManagerService();
try {
sVelocityTrackerStrategy = mIm.getVelocityTrackerStrategy();
} catch (RemoteException ex) {
@@ -324,7 +325,8 @@
@VisibleForTesting
public static InputManager resetInstance(IInputManager inputManagerService) {
synchronized (InputManager.class) {
- sInstance = new InputManager(inputManagerService);
+ InputManagerGlobal.resetInstance(inputManagerService);
+ sInstance = new InputManager();
return sInstance;
}
}
@@ -337,6 +339,7 @@
@VisibleForTesting
public static void clearInstance() {
synchronized (InputManager.class) {
+ InputManagerGlobal.clearInstance();
sInstance = null;
}
}
@@ -364,13 +367,7 @@
public static InputManager getInstance(Context context) {
synchronized (InputManager.class) {
if (sInstance == null) {
- try {
- sInstance = new InputManager(IInputManager.Stub
- .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
-
- } catch (ServiceNotFoundException e) {
- throw new IllegalStateException(e);
- }
+ sInstance = new InputManager();
}
if (sInstance.mWeakContext == null || sInstance.mWeakContext.get() == null) {
sInstance.mWeakContext = new WeakReference(context);
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
new file mode 100644
index 0000000..82dddfc
--- /dev/null
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
+
+/**
+ * Manages communication with the input manager service on behalf of
+ * an application process. You're probably looking for {@link InputManager}.
+ *
+ * @hide
+ */
+public final class InputManagerGlobal {
+ private static final String TAG = "InputManagerGlobal";
+
+ private static InputManagerGlobal sInstance;
+
+ private final IInputManager mIm;
+
+ public InputManagerGlobal(IInputManager im) {
+ mIm = im;
+ }
+
+ /**
+ * Gets an instance of the input manager global singleton.
+ *
+ * @return The display manager instance, may be null early in system startup
+ * before the display manager has been fully initialized.
+ */
+ public static InputManagerGlobal getInstance() {
+ synchronized (InputManagerGlobal.class) {
+ if (sInstance == null) {
+ IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
+ if (b != null) {
+ sInstance = new InputManagerGlobal(IInputManager.Stub.asInterface(b));
+ }
+ }
+ return sInstance;
+ }
+ }
+
+ public IInputManager getInputManagerService() {
+ return mIm;
+ }
+
+ /**
+ * Gets an instance of the input manager.
+ *
+ * @return The input manager instance.
+ */
+ public static InputManagerGlobal resetInstance(IInputManager inputManagerService) {
+ synchronized (InputManager.class) {
+ sInstance = new InputManagerGlobal(inputManagerService);
+ return sInstance;
+ }
+ }
+
+ /**
+ * Clear the instance of the input manager.
+ */
+ public static void clearInstance() {
+ synchronized (InputManagerGlobal.class) {
+ sInstance = null;
+ }
+ }
+}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 9341105..104a8b2 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -475,8 +475,8 @@
*
* @param uid The UID whose status needs to be checked.
* @return {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_DISABLED},
- * {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_ENABLED},
- * or {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_WHITELISTED} to denote
+ * {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_ENABLED},
+ * or {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_WHITELISTED} to denote
* the current status of the UID.
* @hide
*/
@@ -769,6 +769,28 @@
}
/**
+ * Returns the default network capabilities
+ * ({@link ActivityManager#PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
+ * ActivityManager.PROCESS_CAPABILITY_*}) of the specified process state.
+ * This <b>DOES NOT</b> return all default process capabilities for a proc state.
+ * @hide
+ */
+ public static int getDefaultProcessNetworkCapabilities(int procState) {
+ switch (procState) {
+ case ActivityManager.PROCESS_STATE_PERSISTENT:
+ case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
+ case ActivityManager.PROCESS_STATE_TOP:
+ return ActivityManager.PROCESS_CAPABILITY_ALL;
+ case ActivityManager.PROCESS_STATE_BOUND_TOP:
+ case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
+ case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+ return ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
+ default:
+ return ActivityManager.PROCESS_CAPABILITY_NONE;
+ }
+ }
+
+ /**
* Returns true if {@param procState} is considered foreground and as such will be allowed
* to access network when the device is idle or in battery saver mode. Otherwise, false.
* @hide
@@ -784,7 +806,7 @@
public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(
int procState, @ProcessCapability int capability) {
return procState <= FOREGROUND_THRESHOLD_STATE
- || (capability & ActivityManager.PROCESS_CAPABILITY_NETWORK) != 0;
+ || (capability & ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0;
}
/** @hide */
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index e2af9b0..b749d69 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -420,6 +420,7 @@
// Guarded by NfcAdapter.class
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
+ static boolean sHasCeFeature;
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -616,11 +617,13 @@
PackageManager pm;
pm = context.getPackageManager();
sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC);
- boolean hasHceFeature =
+ sHasCeFeature =
pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
- || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
+ || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)
+ || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)
+ || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE);
/* is this device meant to have NFC */
- if (!sHasNfcFeature && !hasHceFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature) {
Log.v(TAG, "this device does not have NFC support");
throw new UnsupportedOperationException();
}
@@ -643,7 +646,7 @@
throw new UnsupportedOperationException();
}
}
- if (hasHceFeature) {
+ if (sHasCeFeature) {
try {
sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface();
} catch (RemoteException e) {
@@ -1669,7 +1672,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean enableSecureNfc(boolean enable) {
- if (!sHasNfcFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature) {
throw new UnsupportedOperationException();
}
try {
@@ -1694,10 +1697,13 @@
* Checks if the device supports Secure NFC functionality.
*
* @return True if device supports Secure NFC, false otherwise
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+ * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+ * are unavailable
*/
public boolean isSecureNfcSupported() {
- if (!sHasNfcFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature) {
throw new UnsupportedOperationException();
}
try {
@@ -1723,11 +1729,14 @@
* such as their relative positioning on the device.
*
* @return Information on the nfc antenna(s) on the device.
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+ * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+ * are unavailable
*/
@Nullable
public NfcAntennaInfo getNfcAntennaInfo() {
- if (!sHasNfcFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature) {
throw new UnsupportedOperationException();
}
try {
@@ -1752,12 +1761,15 @@
* Checks Secure NFC feature is enabled.
*
* @return True if Secure NFC is enabled, false otherwise
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+ * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+ * are unavailable
* @throws UnsupportedOperationException if device doesn't support
* Secure NFC functionality. {@link #isSecureNfcSupported}
*/
public boolean isSecureNfcEnabled() {
- if (!sHasNfcFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature) {
throw new UnsupportedOperationException();
}
try {
@@ -2071,14 +2083,17 @@
* always on.
* @param value if true the NFCC will be kept on (with no RF enabled if NFC adapter is
* disabled), if false the NFCC will follow completely the Nfc adapter state.
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+ * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+ * are unavailable
* @return void
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
public boolean setControllerAlwaysOn(boolean value) {
- if (!sHasNfcFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature) {
throw new UnsupportedOperationException();
}
try {
@@ -2103,7 +2118,10 @@
* Checks NFC controller always on feature is enabled.
*
* @return True if NFC controller always on is enabled, false otherwise
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+ * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+ * are unavailable
* @hide
*/
@SystemApi
@@ -2131,13 +2149,16 @@
* Checks if the device supports NFC controller always on functionality.
*
* @return True if device supports NFC controller always on, false otherwise
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+ * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+ * are unavailable
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
public boolean isControllerAlwaysOnSupported() {
- if (!sHasNfcFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature) {
throw new UnsupportedOperationException();
}
try {
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 0954013..793a70e 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -660,7 +660,7 @@
* @param proto the ProtoOutputStream to write to
*/
public void dumpDebug(ProtoOutputStream proto) {
- getComponent().dumpDebug(proto, ApduServiceInfoProto.COMPONENT_NAME);
+ Utils.dumpDebugComponentName(getComponent(), proto, ApduServiceInfoProto.COMPONENT_NAME);
proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
if (!mOnHost) {
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index f8f7dfe..7a36b26 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -340,7 +340,7 @@
* @param proto the ProtoOutputStream to write to
*/
public void dumpDebug(ProtoOutputStream proto) {
- getComponent().dumpDebug(proto, NfcFServiceInfoProto.COMPONENT_NAME);
+ Utils.dumpDebugComponentName(getComponent(), proto, NfcFServiceInfoProto.COMPONENT_NAME);
proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
proto.write(NfcFServiceInfoProto.NFCID2, getNfcid2());
diff --git a/core/java/android/nfc/cardemulation/Utils.java b/core/java/android/nfc/cardemulation/Utils.java
new file mode 100644
index 0000000..202e1cf
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/Utils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.cardemulation;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.ComponentNameProto;
+import android.util.proto.ProtoOutputStream;
+
+/** @hide */
+public final class Utils {
+ private Utils() {
+ }
+
+ /** Copied from {@link ComponentName#dumpDebug(ProtoOutputStream, long)} */
+ public static void dumpDebugComponentName(
+ @NonNull ComponentName componentName, @NonNull ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(ComponentNameProto.PACKAGE_NAME, componentName.getPackageName());
+ proto.write(ComponentNameProto.CLASS_NAME, componentName.getClassName());
+ proto.end(token);
+ }
+}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3cf3ea2..fcebb45 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -117,6 +117,7 @@
boolean someUserHasAccount(in String accountName, in String accountType);
String getProfileType(int userId);
boolean isDemoUser(int userId);
+ boolean isAdminUser(int userId);
boolean isPreCreated(int userId);
UserInfo createProfileForUserEvenWhenDisallowedWithThrow(in String name, in String userType, int flags,
int userId, in String[] disallowedPackages);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 423fa42..08aea8e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2441,21 +2441,24 @@
}
/**
- * Used to check if the context user is an admin user. An admin user is allowed to
+ * Used to check if the context user is an admin user. An admin user may be allowed to
* modify or configure certain settings that aren't available to non-admin users,
* create and delete additional users, etc. There can be more than one admin users.
*
* @return whether the context user is an admin user.
- * @hide
*/
- @SystemApi
- @RequiresPermission(anyOf = {
- Manifest.permission.MANAGE_USERS,
- Manifest.permission.CREATE_USERS,
- Manifest.permission.QUERY_USERS})
- @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ @UserHandleAware(
+ enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+ requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+ Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.QUERY_USERS})
public boolean isAdminUser() {
- return isUserAdmin(getContextUserIfAppropriate());
+ try {
+ return mService.isAdminUser(getContextUserIfAppropriate());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
@@ -3980,6 +3983,9 @@
* time, the preferred user name and account information are used by the setup process for that
* user.
*
+ * This API should only be called if the current user is an {@link #isAdminUser() admin} user,
+ * as otherwise the returned intent will not be able to create a user.
+ *
* @param userName Optional name to assign to the user.
* @param accountName Optional account name that will be used by the setup wizard to initialize
* the user.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a3f8599..ac78fbc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4385,6 +4385,16 @@
= "wear_accessibility_gesture_enabled";
/**
+ * If the triple press gesture for toggling accessibility is enabled during OOBE.
+ * Set to 1 for true and 0 for false.
+ *
+ * This setting is used only internally.
+ * @hide
+ */
+ public static final String WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE =
+ "wear_accessibility_gesture_enabled_during_oobe";
+
+ /**
* @deprecated Use {@link android.provider.Settings.Global#AIRPLANE_MODE_ON} instead
*/
@Deprecated
@@ -5766,6 +5776,7 @@
PRIVATE_SETTINGS.add(END_BUTTON_BEHAVIOR);
PRIVATE_SETTINGS.add(ADVANCED_SETTINGS);
PRIVATE_SETTINGS.add(WEAR_ACCESSIBILITY_GESTURE_ENABLED);
+ PRIVATE_SETTINGS.add(WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE);
PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
PRIVATE_SETTINGS.add(VOLUME_MASTER);
@@ -8289,6 +8300,15 @@
"accessibility_display_inversion_enabled";
/**
+ * Flag that specifies whether font size has been changed. The flag will
+ * be set when users change the scaled value of font size for the first time.
+ * @hide
+ */
+ @Readable
+ public static final String ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED =
+ "accessibility_font_scaling_has_been_changed";
+
+ /**
* Setting that specifies whether display color space adjustment is
* enabled.
*
@@ -10778,6 +10798,15 @@
"low_power_warning_acknowledged";
/**
+ * Whether the "first time extra battery saver warning" dialog needs to be shown
+ * (0: default) or not (1).
+ *
+ * @hide
+ */
+ public static final String EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED =
+ "extra_low_power_warning_acknowledged";
+
+ /**
* 0 (default) Auto battery saver suggestion has not been suppressed. 1) it has been
* suppressed.
* @hide
@@ -15193,6 +15222,12 @@
public static final String LOW_POWER_MODE = "low_power";
/**
+ * If 1 extra low power mode is enabled.
+ * @hide
+ */
+ public static final String EXTRA_LOW_POWER_MODE = "extra_low_power";
+
+ /**
* If 1, battery saver ({@link #LOW_POWER_MODE}) will be re-activated after the device
* is unplugged from a charger or rebooted.
* @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 6896e02..d14abfd 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4937,4 +4937,66 @@
return ALL_COLUMNS;
}
}
+
+ /**
+ * Stores incoming satellite datagrams.
+ * @hide
+ */
+ public static final class SatelliteDatagrams {
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private SatelliteDatagrams() {}
+
+ /**
+ * Provider name for Satellite Datagrams table.
+ */
+ public static final String PROVIDER_NAME = "satellite";
+
+ /**
+ * Table name for Satellite Datagrams table.
+ */
+ public static final String TABLE_NAME = "incoming_datagrams";
+
+ /**
+ * URL for satellite incoming datagrams table.
+ */
+ private static final String URL = "content://" + PROVIDER_NAME + "/" + TABLE_NAME;
+
+ /**
+ * The {@code content://} style URI for this provider.
+ * @hide
+ */
+ public static final Uri CONTENT_URI = Uri.parse(URL);
+
+ /**
+ * SatelliteProvider unique key column name is the datagram id.
+ * <P>Type: INTEGER (int)</P>
+ * @hide
+ */
+ public static final String COLUMN_UNIQUE_KEY_DATAGRAM_ID = "datagram_id";
+
+ /**
+ * SatelliteProvider column name for storing datagram.
+ * <p>TYPE: BLOB
+ * @hide
+ */
+ public static final String COLUMN_DATAGRAM = "datagram";
+
+ /** All columns in {@link SatelliteDatagrams} table. */
+ private static final List<String> ALL_COLUMNS = List.of(
+ COLUMN_UNIQUE_KEY_DATAGRAM_ID,
+ COLUMN_DATAGRAM
+ );
+
+ /**
+ * @return All columns in {@link SatelliteDatagrams} table.
+ * @hide
+ */
+ @NonNull
+ public static List<String> getAllColumns() {
+ return ALL_COLUMNS;
+ }
+ }
}
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index b0e847c..5d58120 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -233,6 +233,22 @@
*/
public static final int TYPE_DATASETS_SHOWN = 5;
+ /**
+ * The app/user requested for a field to be Autofilled.
+ *
+ * This event is fired when the view has been entered (by user or app) in order
+ * to differentiate from FillRequests that have been pretriggered for FillDialogs.
+ *
+ * For example, the user might navigate away from a screen without tapping any
+ * fields. In this case, a FillRequest/FillResponse has been generated, but was
+ * not used for Autofilling. The user did not intend to see an Autofill result,
+ * but a FillRequest was still generated. This is different from when the user
+ * did tap on a field after the pretriggered FillRequest, this event will appear
+ * in the FillEventHistory, signaling that the user did intend to Autofill
+ * something.
+ */
+ public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6;
+
/** @hide */
@IntDef(prefix = { "TYPE_" }, value = {
TYPE_DATASET_SELECTED,
@@ -240,7 +256,8 @@
TYPE_AUTHENTICATION_SELECTED,
TYPE_SAVE_SHOWN,
TYPE_CONTEXT_COMMITTED,
- TYPE_DATASETS_SHOWN
+ TYPE_DATASETS_SHOWN,
+ TYPE_VIEW_REQUESTED_AUTOFILL
})
@Retention(RetentionPolicy.SOURCE)
@interface EventIds{}
@@ -659,8 +676,8 @@
@Nullable AutofillId[] detectedFieldIds,
@Nullable FieldClassification[] detectedFieldClassifications,
int saveDialogNotShowReason, int uiType) {
- mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN,
- "eventType");
+ mEventType = Preconditions.checkArgumentInRange(eventType, 0,
+ TYPE_VIEW_REQUESTED_AUTOFILL, "eventType");
mDatasetId = datasetId;
mClientState = clientState;
mSelectedDatasetIds = selectedDatasetIds;
@@ -723,6 +740,8 @@
return "TYPE_CONTEXT_COMMITTED";
case TYPE_DATASETS_SHOWN:
return "TYPE_DATASETS_SHOWN";
+ case TYPE_VIEW_REQUESTED_AUTOFILL:
+ return "TYPE_VIEW_REQUESTED_AUTOFILL";
default:
return "TYPE_UNKNOWN";
}
diff --git a/core/java/android/service/credentials/BeginCreateCredentialResponse.java b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
index f0f954d..eebd31c 100644
--- a/core/java/android/service/credentials/BeginCreateCredentialResponse.java
+++ b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
@@ -32,7 +32,7 @@
*/
public final class BeginCreateCredentialResponse implements Parcelable {
private final @NonNull List<CreateEntry> mCreateEntries;
- private final @Nullable CreateEntry mRemoteCreateEntry;
+ private final @Nullable RemoteEntry mRemoteCreateEntry;
/**
* Creates an empty response instance, to be used when there are no {@link CreateEntry}
@@ -46,7 +46,7 @@
List<CreateEntry> createEntries = new ArrayList<>();
in.readTypedList(createEntries, CreateEntry.CREATOR);
mCreateEntries = createEntries;
- mRemoteCreateEntry = in.readTypedObject(CreateEntry.CREATOR);
+ mRemoteCreateEntry = in.readTypedObject(RemoteEntry.CREATOR);
}
@Override
@@ -75,7 +75,7 @@
/* package-private */ BeginCreateCredentialResponse(
@NonNull List<CreateEntry> createEntries,
- @Nullable CreateEntry remoteCreateEntry) {
+ @Nullable RemoteEntry remoteCreateEntry) {
this.mCreateEntries = createEntries;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mCreateEntries);
@@ -88,7 +88,7 @@
}
/** Returns the remote create entry to be displayed on the UI. */
- public @Nullable CreateEntry getRemoteCreateEntry() {
+ public @Nullable RemoteEntry getRemoteCreateEntry() {
return mRemoteCreateEntry;
}
@@ -98,7 +98,7 @@
@SuppressWarnings("WeakerAccess") /* synthetic access */
public static final class Builder {
private @NonNull List<CreateEntry> mCreateEntries = new ArrayList<>();
- private @Nullable CreateEntry mRemoteCreateEntry;
+ private @Nullable RemoteEntry mRemoteCreateEntry;
/**
* Sets the list of create entries to be shown on the UI.
@@ -138,7 +138,7 @@
* {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE} key should be populated
* with a {@link android.credentials.CreateCredentialResponse} object.
*/
- public @NonNull Builder setRemoteCreateEntry(@Nullable CreateEntry remoteCreateEntry) {
+ public @NonNull Builder setRemoteCreateEntry(@Nullable RemoteEntry remoteCreateEntry) {
mRemoteCreateEntry = remoteCreateEntry;
return this;
}
diff --git a/core/java/android/service/credentials/BeginGetCredentialResponse.java b/core/java/android/service/credentials/BeginGetCredentialResponse.java
index 3652742..97f5079 100644
--- a/core/java/android/service/credentials/BeginGetCredentialResponse.java
+++ b/core/java/android/service/credentials/BeginGetCredentialResponse.java
@@ -42,7 +42,7 @@
private final @NonNull List<Action> mActions;
/** Remote credential entry to get the response from a different device. */
- private final @Nullable CredentialEntry mRemoteCredentialEntry;
+ private final @Nullable RemoteEntry mRemoteCredentialEntry;
/**
* Creates an empty response instance, to be used when there are no {@link CredentialEntry},
@@ -57,7 +57,7 @@
private BeginGetCredentialResponse(@NonNull List<CredentialEntry> credentialEntries,
@NonNull List<Action> authenticationEntries, @NonNull List<Action> actions,
- @Nullable CredentialEntry remoteCredentialEntry) {
+ @Nullable RemoteEntry remoteCredentialEntry) {
mCredentialEntries = new ArrayList<>(credentialEntries);
mAuthenticationEntries = new ArrayList<>(authenticationEntries);
mActions = new ArrayList<>(actions);
@@ -74,7 +74,7 @@
List<Action> actions = new ArrayList<>();
in.readTypedList(actions, Action.CREATOR);
mActions = actions;
- mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
+ mRemoteCredentialEntry = in.readTypedObject(RemoteEntry.CREATOR);
}
public static final @NonNull Creator<BeginGetCredentialResponse> CREATOR =
@@ -127,7 +127,7 @@
/**
* Returns the remote credential entry to be displayed on the UI.
*/
- public @Nullable CredentialEntry getRemoteCredentialEntry() {
+ public @Nullable RemoteEntry getRemoteCredentialEntry() {
return mRemoteCredentialEntry;
}
@@ -139,7 +139,7 @@
private List<Action> mAuthenticationEntries = new ArrayList<>();
private List<Action> mActions = new ArrayList<>();
- private CredentialEntry mRemoteCredentialEntry;
+ private RemoteEntry mRemoteCredentialEntry;
/**
* Sets a remote credential entry to be shown on the UI. Provider must set this if they
@@ -155,7 +155,7 @@
* {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE} key should be populated
* with a {@link android.credentials.Credential} object.
*/
- public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
+ public @NonNull Builder setRemoteCredentialEntry(@Nullable RemoteEntry
remoteCredentialEntry) {
mRemoteCredentialEntry = remoteCredentialEntry;
return this;
diff --git a/core/java/android/service/credentials/GetCredentialRequest.java b/core/java/android/service/credentials/GetCredentialRequest.java
index 4f13922..5bad9ab 100644
--- a/core/java/android/service/credentials/GetCredentialRequest.java
+++ b/core/java/android/service/credentials/GetCredentialRequest.java
@@ -23,14 +23,16 @@
import com.android.internal.util.AnnotationValidations;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
* Request for getting user's credential from a given credential provider.
*
- * <p>Provider will receive this request once the user selects a given {@link CredentialEntry}
- * on the selector, that was sourced from provider's result to
- * {@link CredentialProviderService#onBeginGetCredential}.
+ * <p>A credential provider will receive this request once the user selects a
+ * given {@link CredentialEntry}, or {@link RemoteEntry} on the selector, that was sourced
+ * from provider's initial response to {@link CredentialProviderService#onBeginGetCredential}.
*/
public final class GetCredentialRequest implements Parcelable {
/** Calling package of the app requesting for credentials. */
@@ -38,24 +40,27 @@
private final CallingAppInfo mCallingAppInfo;
/**
- * Holds parameters to be used for retrieving a specific type of credential.
+ * Holds a list of options (parameters) to be used for retrieving a specific type of credential.
*/
@NonNull
- private final CredentialOption mCredentialOption;
+ private final List<CredentialOption> mCredentialOptions;
public GetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
- @NonNull CredentialOption credentialOption) {
+ @NonNull List<CredentialOption> credentialOptions) {
this.mCallingAppInfo = Objects.requireNonNull(callingAppInfo,
"callingAppInfo must not be null");
- this.mCredentialOption = Objects.requireNonNull(credentialOption,
- "credentialOption must not be null");
+ this.mCredentialOptions = Objects.requireNonNull(credentialOptions,
+ "credentialOptions must not be null");
}
private GetCredentialRequest(@NonNull Parcel in) {
mCallingAppInfo = in.readTypedObject(CallingAppInfo.CREATOR);
AnnotationValidations.validate(NonNull.class, null, mCallingAppInfo);
- mCredentialOption = in.readTypedObject(CredentialOption.CREATOR);
- AnnotationValidations.validate(NonNull.class, null, mCredentialOption);
+
+ List<CredentialOption> credentialOptions = new ArrayList<>();
+ in.readTypedList(credentialOptions, CredentialOption.CREATOR);
+ mCredentialOptions = credentialOptions;
+ AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
}
@NonNull public static final Creator<GetCredentialRequest> CREATOR =
@@ -79,7 +84,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(mCallingAppInfo, flags);
- dest.writeTypedObject(mCredentialOption, flags);
+ dest.writeTypedList(mCredentialOptions, flags);
}
/**
@@ -91,10 +96,26 @@
}
/**
- * Returns the parameters needed to return a given type of credential.
+ * Returns a list of options containing parameters needed to return a given type of credential.
+ * This is part of the request that the credential provider receives after the user has
+ * selected an entry on a selector UI.
+ *
+ * When the user selects a {@link CredentialEntry} and the credential provider receives a
+ * {@link GetCredentialRequest}, this list is expected to contain a single
+ * {@link CredentialOption} only. A {@link CredentialEntry} is always created for a given
+ * {@link BeginGetCredentialOption}, and hence when the user selects it, the provider
+ * receives a corresponding {@link CredentialOption} that contains all the required parameters
+ * to actually retrieve the credential.
+ *
+ * When the user selects a {@link RemoteEntry} and the credential provider receives a
+ * {@link GetCredentialRequest}, this list may contain greater than a single
+ * {@link CredentialOption}, representing the number of options specified by the developer
+ * in the original {@link android.credentials.GetCredentialRequest}. This is because a
+ * {@link RemoteEntry} indicates that the entire request will be processed on a different
+ * device and is not tied to a particular option.
*/
@NonNull
- public CredentialOption getCredentialOption() {
- return mCredentialOption;
+ public List<CredentialOption> getCredentialOptions() {
+ return mCredentialOptions;
}
}
diff --git a/core/java/android/service/credentials/RemoteEntry.java b/core/java/android/service/credentials/RemoteEntry.java
new file mode 100644
index 0000000..716c00d
--- /dev/null
+++ b/core/java/android/service/credentials/RemoteEntry.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.app.PendingIntent;
+import android.app.slice.Slice;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * An entry to be shown on the UI. This entry represents remote execution of a get/create flow
+ * whereby credentials are retrieved from, or stored to a remote device.
+ *
+ * <p>If user selects this entry, the corresponding {@link PendingIntent} set on the
+ * {@code slice} as a {@link androidx.slice.core.SliceAction} will get invoked.
+ * Once the resulting activity fulfills the required user engagement,
+ * the {@link android.app.Activity} result should be set to {@link android.app.Activity#RESULT_OK},
+ * and the result of the operation must be set as the activity result.
+ *
+ * For a get flow, invoked through {@link CredentialProviderService#onBeginGetCredential},
+ * providers must set a {@link android.credentials.GetCredentialResponse} on the activity result,
+ * against the key {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE}.
+ *
+ * For a creates flow, invoked through {@link CredentialProviderService#onBeginCreateCredential},
+ * providers must set a {@link android.credentials.CreateCredentialResponse} on the activity
+ * result against the ket {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE}.
+ *
+ * <p>Any class that extends this class must only add extra field values to the {@code slice}
+ * object passed into the constructor. Any other field will not be parceled through. If the
+ * derived class has custom parceling implementation, this class will not be able to unpack
+ * the parcel without having access to that implementation.
+ */
+@SuppressLint("ParcelNotFinal")
+public class RemoteEntry implements Parcelable {
+ private final @NonNull Slice mSlice;
+
+ private RemoteEntry(@NonNull Parcel in) {
+ mSlice = in.readTypedObject(Slice.CREATOR);
+ }
+
+ @NonNull
+ public static final Creator<RemoteEntry> CREATOR = new Creator<RemoteEntry>() {
+ @Override
+ public RemoteEntry createFromParcel(@NonNull Parcel in) {
+ return new RemoteEntry(in);
+ }
+
+ @Override
+ public RemoteEntry[] newArray(int size) {
+ return new RemoteEntry[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedObject(mSlice, flags);
+ }
+
+ /**
+ * Constructs a RemoteEntry to be displayed on the UI.
+ *
+ * @param slice the display content to be displayed on the UI, along with this entry
+ */
+ public RemoteEntry(
+ @NonNull Slice slice) {
+ this.mSlice = slice;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSlice);
+ }
+
+ /** Returns the content to be displayed with this remote entry on the UI. */
+ @NonNull
+ public Slice getSlice() {
+ return mSlice;
+ }
+}
diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java
index ff14404..a389223 100644
--- a/core/java/android/service/dreams/DreamActivity.java
+++ b/core/java/android/service/dreams/DreamActivity.java
@@ -70,7 +70,7 @@
@Override
public void onDestroy() {
- if (mCallback != null && !isFinishing()) {
+ if (mCallback != null) {
mCallback.onActivityDestroyed();
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index d79ea89..c7099fd 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -1588,7 +1588,8 @@
// If DreamActivity is destroyed, wake up from Dream.
void onActivityDestroyed() {
mActivity = null;
- onDestroy();
+ mWindow = null;
+ detach();
}
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 3d741cf..4687855 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -553,8 +553,7 @@
}
/**
- * Timestamp of when the trigger event from SoundTriggerHal was received by the system
- * server.
+ * Timestamp of when the trigger event from SoundTriggerHal was received by the framework.
*
* Clock monotonic including suspend time or its equivalent on the system,
* in the same units and timebase as {@link SystemClock#elapsedRealtime()}.
diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java
index 2e455c2..1783186 100644
--- a/core/java/android/service/voice/VisualQueryDetectionService.java
+++ b/core/java/android/service/voice/VisualQueryDetectionService.java
@@ -49,7 +49,7 @@
* {@link VoiceInteractionService#createVisualQueryDetector(PersistableBundle, SharedMemory,
* Executor, VisualQueryDetector.Callback)} is called, the system will bind the application's
* {@link VisualQueryDetectionService}. When requested from {@link VoiceInteractionService}, the
- * system calls into the {@link VisualQueryDetectionService#onStartDetection(Callback)} to enable
+ * system calls into the {@link VisualQueryDetectionService#onStartDetection()} to enable
* detection. This method MUST be implemented to support visual query detection service.
*
* Note: Methods in this class may be called concurrently.
@@ -78,6 +78,8 @@
/** @hide */
public static final String KEY_INITIALIZATION_STATUS = "initialization_status";
+ private IDetectorSessionVisualQueryDetectionCallback mRemoteCallback = null;
+
private final ISandboxedDetectionService mInterface = new ISandboxedDetectionService.Stub() {
@@ -85,7 +87,8 @@
public void detectWithVisualSignals(
IDetectorSessionVisualQueryDetectionCallback callback) {
Log.v(TAG, "#detectWithVisualSignals");
- VisualQueryDetectionService.this.onStartDetection(new Callback(callback));
+ mRemoteCallback = callback;
+ VisualQueryDetectionService.this.onStartDetection();
}
@Override
@@ -178,16 +181,41 @@
/**
* This is called after the service is set up and the client should open the camera and the
- * microphone to start recognition.
- *
- * Called when the {@link VoiceInteractionService} requests that this service
- * {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
+ * microphone to start recognition. When the {@link VoiceInteractionService} requests that this
+ * service {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
* from the device microphone.
- *
- * @param callback The callback to use for responding to the detection request.
- *
+ * <p>
+ * Signal senders that return attention and query results are also expected to be called in this
+ * method according to the detection outcomes.
+ * <p>
+ * On successful user attention, developers should call
+ * {@link VisualQueryDetectionService#gainedAttention()} to enable the streaming of the query.
+ * <p>
+ * On user attention is lost, developers should call
+ * {@link VisualQueryDetectionService#lostAttention()} to disable the streaming of the query.
+ * <p>
+ * On query is detected and ready to stream, developers should call
+ * {@link VisualQueryDetectionService#streamQuery(String)} to return detected query to the
+ * {@link VisualQueryDetector}.
+ * <p>
+ * On streamed query should be rejected, clients should call
+ * {@link VisualQueryDetectionService#rejectQuery()} to abandon query streamed to the
+ * {@link VisualQueryDetector}.
+ * <p>
+ * On streamed query is finished, clients should call
+ * {@link VisualQueryDetectionService#finishQuery()} to complete query streamed to
+ * {@link VisualQueryDetector}.
+ * <p>
+ * Before a call for {@link VisualQueryDetectionService#streamQuery(String)} is triggered,
+ * {@link VisualQueryDetectionService#gainedAttention()} MUST be called to enable the streaming
+ * of query. A query streaming is also expected to be finished by calling either
+ * {@link VisualQueryDetectionService#finishQuery()} or
+ * {@link VisualQueryDetectionService#rejectQuery()} before a new query should start streaming.
+ * When the service enters the state where query streaming should be disabled,
+ * {@link VisualQueryDetectionService#lostAttention()} MUST be called to block unnecessary
+ * streaming.
*/
- public void onStartDetection(@NonNull Callback callback) {
+ public void onStartDetection() {
throw new UnsupportedOperationException();
}
@@ -199,118 +227,78 @@
}
/**
- * Callback for sending out signals and returning query results.
- *
- * On successful user attention, developers should call {@link Callback#onAttentionGained()}
- * to enable the streaming of the query.
- * <p>
- * On user attention is lost, developers should call {@link Callback#onAttentionLost()} to
- * disable the streaming of the query.
- * <p>
- * On query is detected and ready to stream, developers should call
- * {@link Callback#onQueryDetected(String)} to return detected query to the
- * {@link VisualQueryDetector}.
- * <p>
- * On streamed query should be rejected, clients should call {@link Callback#onQueryRejected()}
- * to abandon query streamed to the {@link VisualQueryDetector}.
- * <p>
- * On streamed query is finished, clients should call {@link Callback#onQueryFinished()} to
- * complete query streamed to {@link VisualQueryDetector}.
- * <p>
- * Before a call for {@link Callback#onQueryDetected(String)} is triggered,
- * {@link Callback#onAttentionGained()} MUST be called to enable the streaming of query. A query
- * streaming is also expected to be finished by calling either
- * {@link Callback#onQueryFinished()} or {@link Callback#onQueryRejected()} before a new query
- * should start streaming. When the service enters the state where query streaming should be
- * disabled, {@link Callback#onAttentionLost()} MUST be called to block unnecessary streaming.
+ * Informs the system that the user attention is gained so queries can be streamed.
*/
- public static final class Callback {
-
- // TODO: consider making the constructor a test api for testing purpose
- public Callback() {
- mRemoteCallback = null;
+ public final void gainedAttention() {
+ try {
+ mRemoteCallback.onAttentionGained();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
+ }
- private final IDetectorSessionVisualQueryDetectionCallback mRemoteCallback;
-
- private Callback(IDetectorSessionVisualQueryDetectionCallback remoteCallback) {
- mRemoteCallback = remoteCallback;
+ /**
+ * Informs the system that the user attention is lost to stop streaming.
+ */
+ public final void lostAttention() {
+ try {
+ mRemoteCallback.onAttentionLost();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
+ }
- /**
- * Informs attention listener that the user attention is gained.
- */
- public void onAttentionGained() {
- try {
- mRemoteCallback.onAttentionGained();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ /**
+ * Informs the {@link VisualQueryDetector} with the text content being captured about the
+ * query from the audio source. {@code partialQuery} is provided to the
+ * {@link VisualQueryDetector}. This method is expected to be only triggered if
+ * {@link VisualQueryDetectionService#gainedAttention()} is called to put the service into the
+ * attention gained state.
+ *
+ * @param partialQuery Partially detected query in string.
+ * @throws IllegalStateException if method called without attention gained.
+ */
+ public final void streamQuery(@NonNull String partialQuery) throws IllegalStateException {
+ Objects.requireNonNull(partialQuery);
+ try {
+ mRemoteCallback.onQueryDetected(partialQuery);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#streamQuery must be only be triggered after "
+ + "calling #gainedAttention to be in the attention gained state.");
}
+ }
- /**
- * Informs attention listener that the user attention is lost.
- */
- public void onAttentionLost() {
- try {
- mRemoteCallback.onAttentionLost();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ /**
+ * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
+ * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
+ * {@link VisualQueryDetectionService#streamQuery(String)} is called to put the service into
+ * the query streaming state.
+ *
+ * @throws IllegalStateException if method called without query streamed.
+ */
+ public final void rejectQuery() throws IllegalStateException {
+ try {
+ mRemoteCallback.onQueryRejected();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#rejectQuery must be only be triggered after "
+ + "calling #streamQuery to be in the query streaming state.");
}
+ }
- /**
- * Informs the {@link VisualQueryDetector} with the text content being captured about the
- * query from the audio source. {@code partialQuery} is provided to the
- * {@link VisualQueryDetector}. This method is expected to be only triggered if
- * {@link Callback#onAttentionGained()} is called to put the service into the attention
- * gained state.
- *
- * @param partialQuery Partially detected query in string.
- * @throws IllegalStateException if method called without attention gained.
- */
- public void onQueryDetected(@NonNull String partialQuery) throws IllegalStateException {
- Objects.requireNonNull(partialQuery);
- try {
- mRemoteCallback.onQueryDetected(partialQuery);
- } catch (RemoteException e) {
- throw new IllegalStateException("#onQueryDetected must be only be triggered after "
- + "calling #onAttentionGained to be in the attention gained state.");
- }
- }
-
- /**
- * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
- * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
- * {@link Callback#onQueryDetected()} is called to put the service into the query streaming
- * state.
- *
- * @throws IllegalStateException if method called without query streamed.
- */
- public void onQueryRejected() throws IllegalStateException {
- try {
- mRemoteCallback.onQueryRejected();
- } catch (RemoteException e) {
- throw new IllegalStateException("#onQueryRejected must be only be triggered after "
- + "calling #onQueryDetected to be in the query streaming state.");
- }
- }
-
- /**
- * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
- * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
- * only triggered if {@link Callback#onQueryDetected()} is called to put the service into
- * the query streaming state.
- *
- * @throws IllegalStateException if method called without query streamed.
- */
- public void onQueryFinished() throws IllegalStateException {
- try {
- mRemoteCallback.onQueryFinished();
- } catch (RemoteException e) {
- throw new IllegalStateException("#onQueryFinished must be only be triggered after "
- + "calling #onQueryDetected to be in the query streaming state.");
- }
+ /**
+ * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
+ * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
+ * only triggered if {@link VisualQueryDetectionService#streamQuery(String)} is called to put
+ * the service into the query streaming state.
+ *
+ * @throws IllegalStateException if method called without query streamed.
+ */
+ public final void finishQuery() throws IllegalStateException {
+ try {
+ mRemoteCallback.onQueryFinished();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#finishQuery must be only be triggered after "
+ + "calling #streamQuery to be in the query streaming state.");
}
}
diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
index 0be3253..f0f6a4f 100644
--- a/core/java/android/service/voice/VisualQueryDetector.java
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -177,7 +177,8 @@
public interface Callback {
/**
- * Called when the {@link VisualQueryDetectionService} starts to stream partial queries.
+ * Called when the {@link VisualQueryDetectionService} starts to stream partial queries
+ * with {@link VisualQueryDetectionService#streamQuery(String)}.
*
* @param partialQuery The partial query in a text form being streamed.
*/
@@ -185,12 +186,13 @@
/**
* Called when the {@link VisualQueryDetectionService} decides to abandon the streamed
- * partial queries.
+ * partial queries with {@link VisualQueryDetectionService#rejectQuery()}.
*/
void onQueryRejected();
/**
- * Called when the {@link VisualQueryDetectionService} finishes streaming partial queries.
+ * Called when the {@link VisualQueryDetectionService} finishes streaming partial queries
+ * with {@link VisualQueryDetectionService#finishQuery()}.
*/
void onQueryFinished();
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f53abce..26bc5d12 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1543,14 +1543,14 @@
void doVisibilityChanged(boolean visible) {
if (!mDestroyed) {
mVisible = visible;
- reportVisibility();
+ reportVisibility(false);
if (mReportedVisible) processLocalColors();
} else {
AnimationHandler.requestAnimatorsEnabled(visible, this);
}
}
- void reportVisibility() {
+ void reportVisibility(boolean forceReport) {
if (mScreenshotSurfaceControl != null && mVisible) {
if (DEBUG) Log.v(TAG, "Frozen so don't report visibility change");
return;
@@ -1558,10 +1558,29 @@
if (!mDestroyed) {
mDisplayState = mDisplay == null ? Display.STATE_UNKNOWN : mDisplay.getState();
boolean visible = mVisible && mDisplayState != Display.STATE_OFF;
- if (mReportedVisible != visible) {
+ if (DEBUG) {
+ Log.v(
+ TAG,
+ "reportVisibility"
+ + " mReportedVisible="
+ + mReportedVisible
+ + " mVisible="
+ + mVisible
+ + " mDisplayState="
+ + mDisplayState);
+ }
+ if (mReportedVisible != visible || forceReport) {
mReportedVisible = visible;
- if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible
- + "): " + this);
+ if (DEBUG) {
+ Log.v(
+ TAG,
+ "onVisibilityChanged("
+ + visible
+ + "): "
+ + this
+ + " forceReport="
+ + forceReport);
+ }
if (visible) {
// If becoming visible, in preview mode the surface
// may have been destroyed so now we need to make
@@ -2205,22 +2224,22 @@
}
}
- private final DisplayListener mDisplayListener = new DisplayListener() {
- @Override
- public void onDisplayChanged(int displayId) {
- if (mDisplay.getDisplayId() == displayId) {
- reportVisibility();
- }
- }
+ private final DisplayListener mDisplayListener =
+ new DisplayListener() {
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (mDisplay.getDisplayId() == displayId) {
+ boolean forceReport = mDisplay.getState() != Display.STATE_DOZE_SUSPEND;
+ reportVisibility(forceReport);
+ }
+ }
- @Override
- public void onDisplayRemoved(int displayId) {
- }
+ @Override
+ public void onDisplayRemoved(int displayId) {}
- @Override
- public void onDisplayAdded(int displayId) {
- }
- };
+ @Override
+ public void onDisplayAdded(int displayId) {}
+ };
private Surface getOrCreateBLASTSurface(int width, int height, int format) {
Surface ret = null;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index a746dc6..2ae882c 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -164,10 +164,10 @@
*/
public static final String SETTINGS_AUDIO_ROUTING = "settings_audio_routing";
- /** Flag to enable/disable flash alerts
+ /** Flag to enable/disable flash notifications
* @hide
*/
- public static final String SETTINGS_FLASH_ALERTS = "settings_flash_alerts";
+ public static final String SETTINGS_FLASH_NOTIFICATIONS = "settings_flash_notifications";
/**
* Flag to disable/enable showing udfps enroll view in settings. If it's disabled, udfps enroll
@@ -232,7 +232,7 @@
DEFAULT_FLAGS.put(SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, "false");
DEFAULT_FLAGS.put(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM, "false");
DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false");
- DEFAULT_FLAGS.put(SETTINGS_FLASH_ALERTS, "false");
+ DEFAULT_FLAGS.put(SETTINGS_FLASH_NOTIFICATIONS, "true");
DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "false");
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "false");
diff --git a/core/java/android/util/SparseArrayMap.java b/core/java/android/util/SparseArrayMap.java
index 1a2c4df..b4e1f59 100644
--- a/core/java/android/util/SparseArrayMap.java
+++ b/core/java/android/util/SparseArrayMap.java
@@ -90,6 +90,14 @@
}
/**
+ * Removes the data for the keyIndex and mapIndex, if there was any.
+ * @hide
+ */
+ public void deleteAt(int keyIndex, int mapIndex) {
+ mData.valueAt(keyIndex).removeAt(mapIndex);
+ }
+
+ /**
* Get the value associated with the int-K pair.
*/
@Nullable
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 3cf56c0..6804c5c 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -172,7 +172,7 @@
private boolean isVisibleToAccessibilityService(View view) {
return view != null && (mA11yManager.isRequestFromAccessibilityTool()
- || !view.isAccessibilityDataPrivate());
+ || !view.isAccessibilityDataSensitive());
}
public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 4a83bbe..8c4e90c 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -197,6 +197,7 @@
private int mFPSDivisor = 1;
private DisplayEventReceiver.VsyncEventData mLastVsyncEventData =
new DisplayEventReceiver.VsyncEventData();
+ private final FrameData mFrameData = new FrameData();
/**
* Contains information about the current frame for jank-tracking,
@@ -789,7 +790,7 @@
Trace.traceBegin(Trace.TRACE_TAG_VIEW,
"Choreographer#doFrame " + vsyncEventData.preferredFrameTimeline().vsyncId);
}
- FrameData frameData = new FrameData(frameTimeNanos, vsyncEventData);
+ mFrameData.update(frameTimeNanos, vsyncEventData);
synchronized (mLock) {
if (!mFrameScheduled) {
traceMessage("Frame not scheduled");
@@ -827,7 +828,7 @@
+ " ms in the past.");
}
}
- frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
+ mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos);
}
if (frameTimeNanos < mLastFrameTimeNanos) {
@@ -862,17 +863,16 @@
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
mFrameInfo.markInputHandlingStart();
- doCallbacks(Choreographer.CALLBACK_INPUT, frameData, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_INPUT, frameIntervalNanos);
mFrameInfo.markAnimationsStart();
- doCallbacks(Choreographer.CALLBACK_ANIMATION, frameData, frameIntervalNanos);
- doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameData,
- frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_ANIMATION, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameIntervalNanos);
mFrameInfo.markPerformTraversalsStart();
- doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameData, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameIntervalNanos);
- doCallbacks(Choreographer.CALLBACK_COMMIT, frameData, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_COMMIT, frameIntervalNanos);
} finally {
AnimationUtils.unlockAnimationClock();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
@@ -886,9 +886,9 @@
}
}
- void doCallbacks(int callbackType, FrameData frameData, long frameIntervalNanos) {
+ void doCallbacks(int callbackType, long frameIntervalNanos) {
CallbackRecord callbacks;
- long frameTimeNanos = frameData.mFrameTimeNanos;
+ long frameTimeNanos = mFrameData.mFrameTimeNanos;
synchronized (mLock) {
// We use "now" to determine when callbacks become due because it's possible
// for earlier processing phases in a frame to post callbacks that should run
@@ -925,7 +925,7 @@
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
- frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
+ mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos);
}
}
}
@@ -937,7 +937,7 @@
+ ", action=" + c.action + ", token=" + c.token
+ ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
}
- c.run(frameData);
+ c.run(mFrameData);
}
} finally {
synchronized (mLock) {
@@ -1039,21 +1039,38 @@
/** Holds data that describes one possible VSync frame event to render at. */
public static class FrameTimeline {
- FrameTimeline(long vsyncId, long expectedPresentTimeNanos, long deadlineNanos) {
- this.mVsyncId = vsyncId;
- this.mExpectedPresentTimeNanos = expectedPresentTimeNanos;
- this.mDeadlineNanos = deadlineNanos;
+ private long mVsyncId = FrameInfo.INVALID_VSYNC_ID;
+ private long mExpectedPresentationTimeNanos = -1;
+ private long mDeadlineNanos = -1;
+ private boolean mInCallback = false;
+
+ FrameTimeline() {
+ // Intentionally empty; defined so that it is not API/public by default.
}
- private long mVsyncId;
- private long mExpectedPresentTimeNanos;
- private long mDeadlineNanos;
+ void setInCallback(boolean inCallback) {
+ mInCallback = inCallback;
+ }
+
+ private void checkInCallback() {
+ if (!mInCallback) {
+ throw new IllegalStateException(
+ "FrameTimeline is not valid outside of the vsync callback");
+ }
+ }
+
+ void update(long vsyncId, long expectedPresentationTimeNanos, long deadlineNanos) {
+ mVsyncId = vsyncId;
+ mExpectedPresentationTimeNanos = expectedPresentationTimeNanos;
+ mDeadlineNanos = deadlineNanos;
+ }
/**
* The id that corresponds to this frame timeline, used to correlate a frame
* produced by HWUI with the timeline data stored in Surface Flinger.
*/
public long getVsyncId() {
+ checkInCallback();
return mVsyncId;
}
@@ -1062,13 +1079,15 @@
* presented.
*/
public long getExpectedPresentationTimeNanos() {
- return mExpectedPresentTimeNanos;
+ checkInCallback();
+ return mExpectedPresentationTimeNanos;
}
/**
* The time in {@link System#nanoTime()} timebase which this frame needs to be ready by.
*/
public long getDeadlineNanos() {
+ checkInCallback();
return mDeadlineNanos;
}
}
@@ -1079,24 +1098,21 @@
* information including deadline and expected present time.
*/
public static class FrameData {
- FrameData(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
- this.mFrameTimeNanos = frameTimeNanos;
- this.mFrameTimelines = convertFrameTimelines(vsyncEventData);
- this.mPreferredFrameTimelineIndex =
- vsyncEventData.preferredFrameTimelineIndex;
- }
-
private long mFrameTimeNanos;
- private final FrameTimeline[] mFrameTimelines;
+ private final FrameTimeline[] mFrameTimelines =
+ new FrameTimeline[DisplayEventReceiver.VsyncEventData.FRAME_TIMELINES_LENGTH];
private int mPreferredFrameTimelineIndex;
+ private boolean mInCallback = false;
- void updateFrameData(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
- mFrameTimeNanos = frameTimeNanos;
- mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
+ FrameData() {
+ for (int i = 0; i < mFrameTimelines.length; i++) {
+ mFrameTimelines[i] = new FrameTimeline();
+ }
}
/** The time in nanoseconds when the frame started being rendered. */
public long getFrameTimeNanos() {
+ checkInCallback();
return mFrameTimeNanos;
}
@@ -1104,58 +1120,83 @@
@NonNull
@SuppressLint("ArrayReturn") // For API consistency and speed.
public FrameTimeline[] getFrameTimelines() {
+ checkInCallback();
return mFrameTimelines;
}
/** The platform-preferred frame timeline. */
@NonNull
public FrameTimeline getPreferredFrameTimeline() {
+ checkInCallback();
return mFrameTimelines[mPreferredFrameTimelineIndex];
}
- private FrameTimeline[] convertFrameTimelines(
- DisplayEventReceiver.VsyncEventData vsyncEventData) {
- FrameTimeline[] frameTimelines =
- new FrameTimeline[vsyncEventData.frameTimelines.length];
+ void setInCallback(boolean inCallback) {
+ mInCallback = inCallback;
+ for (int i = 0; i < mFrameTimelines.length; i++) {
+ mFrameTimelines[i].setInCallback(inCallback);
+ }
+ }
+
+ private void checkInCallback() {
+ if (!mInCallback) {
+ throw new IllegalStateException(
+ "FrameData is not valid outside of the vsync callback");
+ }
+ }
+
+ /**
+ * Update the frame data with a {@code DisplayEventReceiver.VsyncEventData} received from
+ * native.
+ */
+ void update(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
+ if (vsyncEventData.frameTimelines.length != mFrameTimelines.length) {
+ throw new IllegalStateException(
+ "Length of native frame timelines received does not match Java. Did "
+ + "FRAME_TIMELINES_LENGTH or kFrameTimelinesLength (native) "
+ + "change?");
+ }
+ mFrameTimeNanos = frameTimeNanos;
+ mPreferredFrameTimelineIndex = vsyncEventData.preferredFrameTimelineIndex;
for (int i = 0; i < vsyncEventData.frameTimelines.length; i++) {
DisplayEventReceiver.VsyncEventData.FrameTimeline frameTimeline =
vsyncEventData.frameTimelines[i];
- frameTimelines[i] = new FrameTimeline(frameTimeline.vsyncId,
- frameTimeline.expectedPresentTime, frameTimeline.deadline);
+ mFrameTimelines[i].update(frameTimeline.vsyncId,
+ frameTimeline.expectedPresentationTime, frameTimeline.deadline);
}
- return frameTimelines;
- }
- }
-
- /**
- * Update the frame data when the frame is late.
- *
- * @param jitterNanos currentTime - frameTime
- */
- private FrameData getUpdatedFrameData(long frameTimeNanos, FrameData frameData,
- long jitterNanos) {
- int newPreferredIndex = 0;
- FrameTimeline[] frameTimelines = frameData.getFrameTimelines();
- final long minimumDeadline =
- frameData.getPreferredFrameTimeline().getDeadlineNanos() + jitterNanos;
- // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
- // query for new frame data. Note that binder is relatively slow, O(ms), so it is
- // only called when the existing frame data does not hold a valid frame.
- while (newPreferredIndex < frameTimelines.length - 1
- && frameTimelines[newPreferredIndex].getDeadlineNanos()
- < minimumDeadline) {
- newPreferredIndex++;
}
- long newPreferredDeadline =
- frameData.getFrameTimelines()[newPreferredIndex].getDeadlineNanos();
- if (newPreferredDeadline < minimumDeadline) {
- DisplayEventReceiver.VsyncEventData latestVsyncEventData =
- mDisplayEventReceiver.getLatestVsyncEventData();
- return new FrameData(frameTimeNanos, latestVsyncEventData);
- } else {
- frameData.updateFrameData(frameTimeNanos, newPreferredIndex);
- return frameData;
+ /**
+ * Update the frame data when the frame is late.
+ *
+ * @param jitterNanos currentTime - frameTime
+ */
+ void update(
+ long frameTimeNanos, DisplayEventReceiver displayEventReceiver, long jitterNanos) {
+ int newPreferredIndex = 0;
+ final long minimumDeadline =
+ mFrameTimelines[mPreferredFrameTimelineIndex].mDeadlineNanos + jitterNanos;
+ // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
+ // query for new frame data. Note that binder is relatively slow, O(ms), so it is
+ // only called when the existing frame data does not hold a valid frame.
+ while (newPreferredIndex < mFrameTimelines.length - 1
+ && mFrameTimelines[newPreferredIndex].mDeadlineNanos < minimumDeadline) {
+ newPreferredIndex++;
+ }
+
+ long newPreferredDeadline = mFrameTimelines[newPreferredIndex].mDeadlineNanos;
+ if (newPreferredDeadline < minimumDeadline) {
+ DisplayEventReceiver.VsyncEventData latestVsyncEventData =
+ displayEventReceiver.getLatestVsyncEventData();
+ update(frameTimeNanos, latestVsyncEventData);
+ } else {
+ update(frameTimeNanos, newPreferredIndex);
+ }
+ }
+
+ void update(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
+ mFrameTimeNanos = frameTimeNanos;
+ mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
}
}
@@ -1280,11 +1321,13 @@
}
void run(FrameData frameData) {
+ frameData.setInCallback(true);
if (token == VSYNC_CALLBACK_TOKEN) {
((VsyncCallback) action).onVsync(frameData);
} else {
run(frameData.getFrameTimeNanos());
}
+ frameData.setInCallback(false);
}
}
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index edce001..07ac597 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -145,11 +145,16 @@
static final FrameTimeline[] INVALID_FRAME_TIMELINES =
{new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)};
+ // The amount of frame timeline choices.
+ // Must be in sync with VsyncEventData::kFrameTimelinesLength in
+ // frameworks/native/libs/gui/include/gui/VsyncEventData.h. If they do not match, a runtime
+ // assertion is thrown when Choreographer is processing VsyncEventData.
+ static final int FRAME_TIMELINES_LENGTH = 7;
public static class FrameTimeline {
- FrameTimeline(long vsyncId, long expectedPresentTime, long deadline) {
+ FrameTimeline(long vsyncId, long expectedPresentationTime, long deadline) {
this.vsyncId = vsyncId;
- this.expectedPresentTime = expectedPresentTime;
+ this.expectedPresentationTime = expectedPresentationTime;
this.deadline = deadline;
}
@@ -158,7 +163,7 @@
public final long vsyncId;
// The frame timestamp for when the frame is expected to be presented.
- public final long expectedPresentTime;
+ public final long expectedPresentationTime;
// The frame deadline timestamp in {@link System#nanoTime()} timebase that it is
// allotted for the frame to be completed.
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 0368918..e31adcf 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -24,6 +24,7 @@
import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
import static android.view.DisplayInfoProto.NAME;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
@@ -37,6 +38,7 @@
import android.os.Process;
import android.util.ArraySet;
import android.util.DisplayMetrics;
+import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.display.BrightnessSynchronizer;
@@ -348,6 +350,12 @@
*/
public float hdrSdrRatio = Float.NaN;
+ /**
+ * RefreshRateRange limitation for @Temperature.ThrottlingStatus
+ */
+ @NonNull
+ public SparseArray<SurfaceControl.RefreshRateRange> refreshRateThermalThrottling =
+ new SparseArray<>();
public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
@Override
@@ -425,7 +433,8 @@
&& installOrientation == other.installOrientation
&& Objects.equals(displayShape, other.displayShape)
&& Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate)
- && BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio);
+ && BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio)
+ && refreshRateThermalThrottling.contentEquals(other.refreshRateThermalThrottling);
}
@Override
@@ -482,6 +491,7 @@
displayShape = other.displayShape;
layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
hdrSdrRatio = other.hdrSdrRatio;
+ refreshRateThermalThrottling = other.refreshRateThermalThrottling;
}
public void readFromParcel(Parcel source) {
@@ -544,6 +554,8 @@
displayShape = source.readTypedObject(DisplayShape.CREATOR);
layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR);
hdrSdrRatio = source.readFloat();
+ refreshRateThermalThrottling = source.readSparseArray(null,
+ SurfaceControl.RefreshRateRange.class);
}
@Override
@@ -604,6 +616,7 @@
dest.writeTypedObject(displayShape, flags);
dest.writeTypedObject(layoutLimitedRefreshRate, flags);
dest.writeFloat(hdrSdrRatio);
+ dest.writeSparseArray(refreshRateThermalThrottling);
}
@Override
@@ -871,6 +884,8 @@
} else {
sb.append(hdrSdrRatio);
}
+ sb.append(", refreshRateThermalThrottling ");
+ sb.append(refreshRateThermalThrottling);
sb.append("}");
return sb.toString();
}
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index 98f61a3..fa92612 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -172,9 +172,13 @@
if (candidateView == getConnectedView()) {
startHandwriting(candidateView);
} else if (candidateView.getHandwritingDelegatorCallback() != null) {
+ String delegatePackageName =
+ candidateView.getAllowedHandwritingDelegatePackageName();
+ if (delegatePackageName == null) {
+ delegatePackageName = candidateView.getContext().getOpPackageName();
+ }
mImm.prepareStylusHandwritingDelegation(
- candidateView,
- candidateView.getAllowedHandwritingDelegatePackageName());
+ candidateView, delegatePackageName);
candidateView.getHandwritingDelegatorCallback().run();
} else {
if (candidateView.getRevealOnFocusHint()) {
@@ -299,8 +303,12 @@
*/
@VisibleForTesting
public boolean tryAcceptStylusHandwritingDelegation(@NonNull View view) {
- if (mImm.acceptStylusHandwritingDelegation(
- view, view.getAllowedHandwritingDelegatorPackageName())) {
+ String delegatorPackageName =
+ view.getAllowedHandwritingDelegatorPackageName();
+ if (delegatorPackageName == null) {
+ delegatorPackageName = view.getContext().getOpPackageName();
+ }
+ if (mImm.acceptStylusHandwritingDelegation(view, delegatorPackageName)) {
if (mState != null) {
mState.mHasInitiatedHandwriting = true;
mState.mShouldInitHandwriting = false;
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index e02e600..3947738 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -20,7 +20,6 @@
import static android.view.InsetsSourceProto.TYPE;
import static android.view.InsetsSourceProto.VISIBLE;
import static android.view.InsetsSourceProto.VISIBLE_FRAME;
-import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
import static android.view.WindowInsets.Type.ime;
import android.annotation.IntRange;
@@ -169,7 +168,7 @@
// During drag-move and drag-resizing, the caption insets position may not get updated
// before the app frame get updated. To layout the app content correctly during drag events,
// we always return the insets with the corresponding height covering the top.
- if (!CAPTION_ON_SHELL && getType() == WindowInsets.Type.captionBar()) {
+ if (getType() == WindowInsets.Type.captionBar()) {
return Insets.of(0, frame.height(), 0, 0);
}
// Checks for whether there is shared edge with insets for 0-width/height window.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fee2051..869efc69 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3114,33 +3114,33 @@
* Accessibility interactions from services without {@code isAccessibilityTool} set to true are
* disallowed for any of the following conditions:
* <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li>
- * <li>any parent of this view returns true from {@link #isAccessibilityDataPrivate()}.</li>
+ * <li>any parent of this view returns true from {@link #isAccessibilityDataSensitive()}.</li>
* </p>
*/
- public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0x00000000;
+ public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0x00000000;
/**
* Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s
* with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool}
* property set to true.
*/
- public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 0x00000001;
+ public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 0x00000001;
/**
* Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s,
* regardless of their
* {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property.
*/
- public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 0x00000002;
+ public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 0x00000002;
/** @hide */
- @IntDef(prefix = { "ACCESSIBILITY_DATA_PRIVATE_" }, value = {
- ACCESSIBILITY_DATA_PRIVATE_AUTO,
- ACCESSIBILITY_DATA_PRIVATE_YES,
- ACCESSIBILITY_DATA_PRIVATE_NO,
+ @IntDef(prefix = { "ACCESSIBILITY_DATA_SENSITIVE_" }, value = {
+ ACCESSIBILITY_DATA_SENSITIVE_AUTO,
+ ACCESSIBILITY_DATA_SENSITIVE_YES,
+ ACCESSIBILITY_DATA_SENSITIVE_NO,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface AccessibilityDataPrivate {}
+ public @interface AccessibilityDataSensitive {}
/**
* Mask for obtaining the bits which specify how to determine
@@ -4611,9 +4611,9 @@
* {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
* set to true.
*/
- private int mExplicitAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
- /** Used to calculate and cache {@link #isAccessibilityDataPrivate()}. */
- private int mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
+ private int mExplicitAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
+ /** Used to calculate and cache {@link #isAccessibilityDataSensitive()}. */
+ private int mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
/**
* Specifies the id of a view for which this view serves as a label for
@@ -6016,9 +6016,9 @@
setImportantForAccessibility(a.getInt(attr,
IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
break;
- case R.styleable.View_accessibilityDataPrivate:
- setAccessibilityDataPrivate(a.getInt(attr,
- ACCESSIBILITY_DATA_PRIVATE_AUTO));
+ case R.styleable.View_accessibilityDataSensitive:
+ setAccessibilityDataSensitive(a.getInt(attr,
+ ACCESSIBILITY_DATA_SENSITIVE_AUTO));
break;
case R.styleable.View_accessibilityLiveRegion:
setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
@@ -8660,9 +8660,9 @@
* is responsible for handling this call.
* </p>
* <p>
- * If this view sets {@link #isAccessibilityDataPrivate()} then this view should only append
+ * If this view sets {@link #isAccessibilityDataSensitive()} then this view should only append
* sensitive information to an event that also sets
- * {@link AccessibilityEvent#isAccessibilityDataPrivate()}.
+ * {@link AccessibilityEvent#isAccessibilityDataSensitive()}.
* </p>
* <p>
* <em>Note:</em> Accessibility events of certain types are not dispatched for
@@ -10697,6 +10697,7 @@
info.setVisibleToUser(isVisibleToUser());
info.setImportantForAccessibility(isImportantForAccessibility());
+ info.setAccessibilityDataSensitive(isAccessibilityDataSensitive());
info.setPackageName(mContext.getPackageName());
info.setClassName(getAccessibilityClassName());
info.setStateDescription(getStateDescription());
@@ -12437,11 +12438,7 @@
public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
mHandwritingDelegatorCallback = callback;
if (callback != null) {
- // By default, the delegate must be from the same package as the delegator view.
- mAllowedHandwritingDelegatePackageName = mContext.getOpPackageName();
setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
- } else {
- mAllowedHandwritingDelegatePackageName = null;
}
}
@@ -12460,8 +12457,10 @@
* view from the specified package. If this method is not called, delegators may only be used to
* initiate handwriting mode for a delegate editor view from the same package as the delegator
* view. This method allows specifying a different trusted package which may contain a delegate
- * editor view linked to this delegator view. This should be called after {@link
- * #setHandwritingDelegatorCallback}.
+ * editor view linked to this delegator view.
+ *
+ * <p>This method has no effect unless {@link #setHandwritingDelegatorCallback} is also called
+ * to configure this view to act as a handwriting delegator.
*
* <p>If this method is called on the delegator view, then {@link
* #setAllowedHandwritingDelegatorPackage} should also be called on the delegate editor view.
@@ -12479,33 +12478,23 @@
* delegateEditorView.setAllowedHandwritingDelegatorPackage(package1);</pre>
*
* @param allowedPackageName the package name of a delegate editor view linked to this delegator
- * view
- * @throws IllegalStateException If the view has not been configured as a handwriting delegator
- * using {@link #setHandwritingDelegatorCallback}.
+ * view, or {@code null} to restore the default behavior of only allowing delegate editor
+ * views from the same package as this delegator view
*/
- public void setAllowedHandwritingDelegatePackage(@NonNull String allowedPackageName) {
- if (mHandwritingDelegatorCallback == null) {
- throw new IllegalStateException("This view is not a handwriting delegator.");
- }
+ public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
mAllowedHandwritingDelegatePackageName = allowedPackageName;
}
/**
* Returns the allowed package for delegate editor views for which this view may act as a
- * handwriting delegator. If {@link #setAllowedHandwritingDelegatePackage} has not been called,
- * this will return this view's package name, since by default delegators may only be used to
- * initiate handwriting mode for a delegate editor view from the same package as the delegator
- * view. This will return a different allowed package if set by {@link
- * #setAllowedHandwritingDelegatePackage}.
- *
- * @throws IllegalStateException If the view has not been configured as a handwriting delegator
- * using {@link #setHandwritingDelegatorCallback}.
+ * handwriting delegator, as set by {@link #setAllowedHandwritingDelegatePackage}. If {@link
+ * #setAllowedHandwritingDelegatePackage} has not been called, or called with {@code null}
+ * argument, this will return {@code null}, meaning that this delegator view may only be used to
+ * initiate handwriting mode for a delegate editor view from the same package as this delegator
+ * view.
*/
- @NonNull
+ @Nullable
public String getAllowedHandwritingDelegatePackageName() {
- if (mHandwritingDelegatorCallback == null) {
- throw new IllegalStateException("This view is not a handwriting delegator.");
- }
return mAllowedHandwritingDelegatePackageName;
}
@@ -12519,12 +12508,6 @@
*/
public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
mIsHandwritingDelegate = isHandwritingDelegate;
- if (mIsHandwritingDelegate) {
- // By default, the delegator must be from the same package as the delegate view.
- mAllowedHandwritingDelegatorPackageName = mContext.getOpPackageName();
- } else {
- mAllowedHandwritingDelegatePackageName = null;
- }
}
/**
@@ -12537,41 +12520,34 @@
/**
* Specifies that a view from the specified package may act as a handwriting delegator for this
- * delegate editor view. If this method is not called, only views from the same package as the
+ * delegate editor view. If this method is not called, only views from the same package as this
* delegate editor view may act as a handwriting delegator. This method allows specifying a
* different trusted package which may contain a delegator view linked to this delegate editor
- * view. This should be called after {@link #setIsHandwritingDelegate}.
+ * view.
+ *
+ * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
+ * configure this view to act as a handwriting delegate.
*
* <p>If this method is called on the delegate editor view, then {@link
* #setAllowedHandwritingDelegatePackage} should also be called on the delegator view.
*
* @param allowedPackageName the package name of a delegator view linked to this delegate editor
- * view
- * @throws IllegalStateException If the view has not been configured as a handwriting delegate
- * using {@link #setIsHandwritingDelegate}.
+ * view, or {@code null} to restore the default behavior of only allowing delegator views
+ * from the same package as this delegate editor view
*/
- public void setAllowedHandwritingDelegatorPackage(@NonNull String allowedPackageName) {
- if (!mIsHandwritingDelegate) {
- throw new IllegalStateException("This view is not a handwriting delegate.");
- }
+ public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
mAllowedHandwritingDelegatorPackageName = allowedPackageName;
}
/**
* Returns the allowed package for views which may act as a handwriting delegator for this
- * delegate editor view. If {@link #setAllowedHandwritingDelegatorPackage} has not been called,
- * this will return this view's package name, since by default only views from the same package
- * as the delegator editor view may act as a handwriting delegator. This will return a different
- * allowed package if set by {@link #setAllowedHandwritingDelegatorPackage}.
- *
- * @throws IllegalStateException If the view has not been configured as a handwriting delegate
- * using {@link #setIsHandwritingDelegate}.
+ * delegate editor view, as set by {@link #setAllowedHandwritingDelegatorPackage}. If {@link
+ * #setAllowedHandwritingDelegatorPackage} has not been called, or called with {@code null}
+ * argument, this will return {@code null}, meaning that only views from the same package as
+ * this delegator editor view may act as a handwriting delegator.
*/
- @NonNull
+ @Nullable
public String getAllowedHandwritingDelegatorPackageName() {
- if (!mIsHandwritingDelegate) {
- throw new IllegalStateException("This view is not a handwriting delegate.");
- }
return mAllowedHandwritingDelegatorPackageName;
}
@@ -13606,7 +13582,7 @@
public void setFilterTouchesWhenObscured(boolean enabled) {
setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
FILTER_TOUCHES_WHEN_OBSCURED);
- calculateAccessibilityDataPrivate();
+ calculateAccessibilityDataSensitive();
}
/**
@@ -14842,7 +14818,7 @@
// source View's AccessibilityDataPrivate value, and then filtering is done when
// AccessibilityManagerService propagates events to each recipient AccessibilityService.
if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
- && isAccessibilityDataPrivate()) {
+ && isAccessibilityDataSensitive()) {
return false;
}
}
@@ -14858,43 +14834,43 @@
* set to true.
*
* <p>
- * See default behavior provided by {@link #ACCESSIBILITY_DATA_PRIVATE_AUTO}. Otherwise,
- * returns true for {@link #ACCESSIBILITY_DATA_PRIVATE_YES} or false for {@link
- * #ACCESSIBILITY_DATA_PRIVATE_NO}.
+ * See default behavior provided by {@link #ACCESSIBILITY_DATA_SENSITIVE_AUTO}. Otherwise,
+ * returns true for {@link #ACCESSIBILITY_DATA_SENSITIVE_YES} or false for {@link
+ * #ACCESSIBILITY_DATA_SENSITIVE_NO}.
* </p>
*
* @return True if this view should restrict accessibility service access to services that have
* the isAccessibilityTool property.
*/
@ViewDebug.ExportedProperty(category = "accessibility")
- public boolean isAccessibilityDataPrivate() {
- if (mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_AUTO) {
- calculateAccessibilityDataPrivate();
+ public boolean isAccessibilityDataSensitive() {
+ if (mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
+ calculateAccessibilityDataSensitive();
}
- return mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_YES;
+ return mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_YES;
}
/**
- * Calculate and cache the inferred value for {@link #isAccessibilityDataPrivate()}.
+ * Calculate and cache the inferred value for {@link #isAccessibilityDataSensitive()}.
*
* <p>
* <strong>Note:</strong> This method needs to be called any time one of the below conditions
* changes, to recalculate the new value.
* </p>
*/
- void calculateAccessibilityDataPrivate() {
+ void calculateAccessibilityDataSensitive() {
// Use the explicit value if set.
- if (mExplicitAccessibilityDataPrivate != ACCESSIBILITY_DATA_PRIVATE_AUTO) {
- mInferredAccessibilityDataPrivate = mExplicitAccessibilityDataPrivate;
+ if (mExplicitAccessibilityDataSensitive != ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
+ mInferredAccessibilityDataSensitive = mExplicitAccessibilityDataSensitive;
} else if (getFilterTouchesWhenObscured()) {
- // Views that set filterTouchesWhenObscured default to accessibilityDataPrivate.
- mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
- } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataPrivate()) {
- // Descendants of an accessibilityDataPrivate View are also accessibilityDataPrivate.
- mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
+ // Views that set filterTouchesWhenObscured default to accessibilityDataSensitive.
+ mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
+ } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataSensitive()) {
+ // Descendants of accessibilityDataSensitive Views are also accessibilityDataSensitive.
+ mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
} else {
- // Otherwise, default to not accessibilityDataPrivate.
- mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_NO;
+ // Otherwise, default to not accessibilityDataSensitive.
+ mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_NO;
}
}
@@ -14904,10 +14880,10 @@
* {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
* set to true.
*/
- public void setAccessibilityDataPrivate(
- @AccessibilityDataPrivate int accessibilityDataPrivate) {
- mExplicitAccessibilityDataPrivate = accessibilityDataPrivate;
- calculateAccessibilityDataPrivate();
+ public void setAccessibilityDataSensitive(
+ @AccessibilityDataSensitive int accessibilityDataSensitive) {
+ mExplicitAccessibilityDataSensitive = accessibilityDataSensitive;
+ calculateAccessibilityDataSensitive();
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 73d4471..46ae3ea 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3921,10 +3921,10 @@
}
@Override
- void calculateAccessibilityDataPrivate() {
- super.calculateAccessibilityDataPrivate();
+ void calculateAccessibilityDataSensitive() {
+ super.calculateAccessibilityDataSensitive();
for (int i = 0; i < mChildrenCount; i++) {
- mChildren[i].calculateAccessibilityDataPrivate();
+ mChildren[i].calculateAccessibilityDataSensitive();
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f430ec3..807af5b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1650,6 +1650,7 @@
mAttachInfo.mThreadedRenderer = renderer;
renderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
updateColorModeIfNeeded(attrs.getColorMode());
+ updateRenderHdrSdrRatio();
updateForceDarkMode();
mAttachInfo.mHardwareAccelerated = true;
mAttachInfo.mHardwareAccelerationRequested = true;
@@ -5379,6 +5380,11 @@
}
}
+ private void updateRenderHdrSdrRatio() {
+ mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
+ mUpdateHdrSdrRatioInfo = true;
+ }
+
private void updateColorModeIfNeeded(@ActivityInfo.ColorMode int colorMode) {
if (mAttachInfo.mThreadedRenderer == null) {
return;
@@ -5396,8 +5402,7 @@
float desiredRatio = mAttachInfo.mThreadedRenderer.setColorMode(colorMode);
if (desiredRatio != mDesiredHdrSdrRatio) {
mDesiredHdrSdrRatio = desiredRatio;
- mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
- mUpdateHdrSdrRatioInfo = true;
+ updateRenderHdrSdrRatio();
if (mDesiredHdrSdrRatio < 1.01f) {
mDisplay.unregisterHdrSdrRatioChangedListener(mHdrSdrRatioChangedListener);
@@ -8496,6 +8501,7 @@
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
}
+ updateRenderHdrSdrRatio();
if (mPreviousTransformHint != transformHint) {
mPreviousTransformHint = transformHint;
dispatchTransformHintChanged(transformHint);
@@ -10078,9 +10084,12 @@
}
void checkThread() {
- if (mThread != Thread.currentThread()) {
+ Thread current = Thread.currentThread();
+ if (mThread != current) {
throw new CalledFromWrongThreadException(
- "Only the original thread that created a view hierarchy can touch its views.");
+ "Only the original thread that created a view hierarchy can touch its views."
+ + " Expected: " + mThread.getName()
+ + " Calling: " + current.getName());
}
}
@@ -11382,6 +11391,10 @@
sendBackKeyEvent(KeyEvent.ACTION_DOWN);
sendBackKeyEvent(KeyEvent.ACTION_UP);
};
+ if (mOnBackInvokedDispatcher.hasImeOnBackInvokedDispatcher()) {
+ Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher");
+ return;
+ }
mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback);
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e7cefd6..f863678 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -817,6 +817,15 @@
}
/**
+ * If the display {@link Configuration#smallestScreenWidthDp} is greater or equal to this value,
+ * we will treat it as a large screen device, which will have some multi window features enabled
+ * by default.
+ * @hide
+ */
+ @TestApi
+ int LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP = 600;
+
+ /**
* Application level {@link android.content.pm.PackageManager.Property PackageManager
* .Property} for an app to inform the system that the app can be opted-in or opted-out
* from the compatibility treatment that avoids {@link
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 33b763b..0acc022 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -56,7 +56,7 @@
* accessibility service has not requested to retrieve the window content the event will
* not contain reference to its source. <strong>Note: </strong> for events of type
* {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available, and Views that set
- * {@link android.view.View#isAccessibilityDataPrivate()} may not populate all event properties on
+ * {@link android.view.View#isAccessibilityDataSensitive()} may not populate all event properties on
* events sent from higher up in the view hierarchy.
* </p>
* <p>
@@ -1168,17 +1168,17 @@
* set to true.
*
* <p>
- * Initial value matches the {@link android.view.View#isAccessibilityDataPrivate} property from
- * the event's source node, if present, or false by default.
+ * Initial value matches the {@link android.view.View#isAccessibilityDataSensitive} property
+ * from the event's source node, if present, or false by default.
* </p>
*
* @return True if the event should be delivered only to isAccessibilityTool services, false
* otherwise.
- * @see #setAccessibilityDataPrivate
+ * @see #setAccessibilityDataSensitive
*/
@Override
- public boolean isAccessibilityDataPrivate() {
- return super.isAccessibilityDataPrivate();
+ public boolean isAccessibilityDataSensitive() {
+ return super.isAccessibilityDataSensitive();
}
/**
@@ -1193,13 +1193,13 @@
* no source) then this method must be called explicitly if you want non-default behavior.
* </p>
*
- * @param accessibilityDataPrivate True if the event should be delivered only to
+ * @param accessibilityDataSensitive True if the event should be delivered only to
* isAccessibilityTool services, false otherwise.
* @throws IllegalStateException If called from an AccessibilityService.
*/
@Override
- public void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
- super.setAccessibilityDataPrivate(accessibilityDataPrivate);
+ public void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
+ super.setAccessibilityDataSensitive(accessibilityDataSensitive);
}
/**
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 247e026..9d82b79 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -834,6 +834,8 @@
private static final int BOOLEAN_PROPERTY_REQUEST_TOUCH_PASSTHROUGH = 1 << 25;
+ private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 1 << 26;
+
/**
* Bits that provide the id of a virtual descendant of a view.
*/
@@ -2644,6 +2646,34 @@
}
/**
+ * Gets if the node's accessibility data is considered sensitive.
+ *
+ * @return True if the node is editable, false otherwise.
+ * @see View#isAccessibilityDataSensitive()
+ */
+ public boolean isAccessibilityDataSensitive() {
+ return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE);
+ }
+
+ /**
+ * Sets whether this node's accessibility data is considered sensitive.
+ *
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an {@link AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param accessibilityDataSensitive True if the node's accessibility data is considered
+ * sensitive.
+ * @throws IllegalStateException If called from an AccessibilityService.
+ * @see View#setAccessibilityDataSensitive
+ */
+ public void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
+ setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE,
+ accessibilityDataSensitive);
+ }
+
+ /**
* If this node represents a visually distinct region of the screen that may update separately
* from the rest of the window, it is considered a pane. Set the pane title to indicate that
* the node is a pane, and to provide a title for it.
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 789c740..38b564a 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -72,7 +72,7 @@
private static final int PROPERTY_FULL_SCREEN = 0x00000080;
private static final int PROPERTY_SCROLLABLE = 0x00000100;
private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
- private static final int PROPERTY_ACCESSIBILITY_DATA_PRIVATE = 0x00000400;
+ private static final int PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 0x00000400;
private static final int GET_SOURCE_PREFETCH_FLAGS =
AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS
@@ -160,8 +160,8 @@
important = root.isImportantForAccessibility();
rootViewId = root.getAccessibilityViewId();
mSourceWindowId = root.getAccessibilityWindowId();
- setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE,
- root.isAccessibilityDataPrivate());
+ setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE,
+ root.isAccessibilityDataSensitive());
}
setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
@@ -391,20 +391,20 @@
}
/**
- * @see AccessibilityEvent#isAccessibilityDataPrivate
+ * @see AccessibilityEvent#isAccessibilityDataSensitive
* @hide
*/
- boolean isAccessibilityDataPrivate() {
- return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE);
+ boolean isAccessibilityDataSensitive() {
+ return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE);
}
/**
- * @see AccessibilityEvent#setAccessibilityDataPrivate
+ * @see AccessibilityEvent#setAccessibilityDataSensitive
* @hide
*/
- void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
+ void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
enforceNotSealed();
- setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE, accessibilityDataPrivate);
+ setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE, accessibilityDataSensitive);
}
/**
@@ -962,7 +962,7 @@
appendUnless(false, PROPERTY_FULL_SCREEN, builder);
appendUnless(false, PROPERTY_SCROLLABLE, builder);
appendUnless(false, PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, builder);
- appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_PRIVATE, builder);
+ appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_SENSITIVE, builder);
append(builder, "BeforeText", mBeforeText);
append(builder, "FromIndex", mFromIndex);
@@ -996,8 +996,8 @@
case PROPERTY_SCROLLABLE: return "Scrollable";
case PROPERTY_IMPORTANT_FOR_ACCESSIBILITY:
return "ImportantForAccessibility";
- case PROPERTY_ACCESSIBILITY_DATA_PRIVATE:
- return "AccessibilityDataPrivate";
+ case PROPERTY_ACCESSIBILITY_DATA_SENSITIVE:
+ return "AccessibilityDataSensitive";
default: return Integer.toHexString(prop);
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index d84e0fb..13ac329 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -839,6 +839,7 @@
mConnectionId = UNDEFINED_WINDOW_ID;
mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
mTitle = null;
+ mTransitionTime = 0;
}
/**
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
index 26c59a6..622b0e2 100644
--- a/core/java/android/view/autofill/OWNERS
+++ b/core/java/android/view/autofill/OWNERS
@@ -1,10 +1,6 @@
# Bug component: 351486
-augale@google.com
-haoranzhang@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
simranjit@google.com
-tymtsai@google.com
+haoranzhang@google.com
+skxu@google.com
yunicorn@google.com
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index b7f03e1..62044aa 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -182,6 +182,10 @@
/** @hide */
public static final int FLUSH_REASON_VIEW_TREE_APPEARED = 10;
+ /**
+ * After {@link UPSIDE_DOWN_CAKE}, {@link #notifyViewsDisappeared(AutofillId, long[])} wraps
+ * the virtual children with a pair of view tree appearing and view tree appeared events.
+ */
@ChangeId
@EnabledSince(targetSdkVersion = UPSIDE_DOWN_CAKE)
static final long NOTIFY_NODES_DISAPPEAR_NOW_SENDS_TREE_EVENTS = 258825825L;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fd8f549..1600a16 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13221,10 +13221,10 @@
public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
super.onPopulateAccessibilityEventInternal(event);
- if (this.isAccessibilityDataPrivate() && !event.isAccessibilityDataPrivate()) {
- // This view's accessibility data is private, but another view that generated this event
- // is not, so don't append this view's text to the event in order to prevent sharing
- // this view's contents with non-accessibility-tool services.
+ if (this.isAccessibilityDataSensitive() && !event.isAccessibilityDataSensitive()) {
+ // This view's accessibility data is sensitive, but another view that generated this
+ // event is not, so don't append this view's text to the event in order to prevent
+ // sharing this view's contents with non-accessibility-tool services.
return;
}
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index a881a05..fa51957 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -66,6 +66,13 @@
@NonNull
private final List<IBinder> mActivities = new ArrayList<>();
+ /**
+ * List of Activity tokens that were explicitly requested to be launched in this TaskFragment.
+ * It only contains Activities that belong to the organizer process for security.
+ */
+ @NonNull
+ private final List<IBinder> mInRequestedTaskFragmentActivities = new ArrayList<>();
+
/** Relative position of the fragment's top left corner in the parent container. */
private final Point mPositionInParent = new Point();
@@ -99,15 +106,18 @@
public TaskFragmentInfo(
@NonNull IBinder fragmentToken, @NonNull WindowContainerToken token,
@NonNull Configuration configuration, int runningActivityCount,
- boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
- boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip,
- boolean isClearedForReorderActivityToFront, @NonNull Point minimumDimensions) {
+ boolean isVisible, @NonNull List<IBinder> activities,
+ @NonNull List<IBinder> inRequestedTaskFragmentActivities,
+ @NonNull Point positionInParent, boolean isTaskClearedForReuse,
+ boolean isTaskFragmentClearedForPip, boolean isClearedForReorderActivityToFront,
+ @NonNull Point minimumDimensions) {
mFragmentToken = requireNonNull(fragmentToken);
mToken = requireNonNull(token);
mConfiguration.setTo(configuration);
mRunningActivityCount = runningActivityCount;
mIsVisible = isVisible;
mActivities.addAll(activities);
+ mInRequestedTaskFragmentActivities.addAll(inRequestedTaskFragmentActivities);
mPositionInParent.set(positionInParent);
mIsTaskClearedForReuse = isTaskClearedForReuse;
mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
@@ -151,6 +161,11 @@
return mActivities;
}
+ @NonNull
+ public List<IBinder> getActivitiesRequestedInTaskFragment() {
+ return mInRequestedTaskFragmentActivities;
+ }
+
/** Returns the relative position of the fragment's top left corner in the parent container. */
@NonNull
public Point getPositionInParent() {
@@ -215,6 +230,8 @@
&& mIsVisible == that.mIsVisible
&& getWindowingMode() == that.getWindowingMode()
&& mActivities.equals(that.mActivities)
+ && mInRequestedTaskFragmentActivities.equals(
+ that.mInRequestedTaskFragmentActivities)
&& mPositionInParent.equals(that.mPositionInParent)
&& mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
&& mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
@@ -229,6 +246,7 @@
mRunningActivityCount = in.readInt();
mIsVisible = in.readBoolean();
in.readBinderList(mActivities);
+ in.readBinderList(mInRequestedTaskFragmentActivities);
mPositionInParent.readFromParcel(in);
mIsTaskClearedForReuse = in.readBoolean();
mIsTaskFragmentClearedForPip = in.readBoolean();
@@ -245,6 +263,7 @@
dest.writeInt(mRunningActivityCount);
dest.writeBoolean(mIsVisible);
dest.writeBinderList(mActivities);
+ dest.writeBinderList(mInRequestedTaskFragmentActivities);
mPositionInParent.writeToParcel(dest, flags);
dest.writeBoolean(mIsTaskClearedForReuse);
dest.writeBoolean(mIsTaskFragmentClearedForPip);
@@ -274,6 +293,7 @@
+ " runningActivityCount=" + mRunningActivityCount
+ " isVisible=" + mIsVisible
+ " activities=" + mActivities
+ + " inRequestedTaskFragmentActivities" + mInRequestedTaskFragmentActivities
+ " positionInParent=" + mPositionInParent
+ " isTaskClearedForReuse=" + mIsTaskClearedForReuse
+ " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index a8c2b2f..8066f50 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -357,6 +357,11 @@
mImeDispatcher = imeDispatcher;
}
+ /** Returns true if a non-null {@link ImeOnBackInvokedDispatcher} has been set. **/
+ public boolean hasImeOnBackInvokedDispatcher() {
+ return mImeDispatcher != null;
+ }
+
/**
* Class used to check whether a callback can be registered or not. This is meant to be
* shared with {@link ProxyOnBackInvokedDispatcher} which needs to do the same checks.
diff --git a/core/java/com/android/internal/app/procstats/UidState.java b/core/java/com/android/internal/app/procstats/UidState.java
index 8761b74..4911346 100644
--- a/core/java/com/android/internal/app/procstats/UidState.java
+++ b/core/java/com/android/internal/app/procstats/UidState.java
@@ -150,6 +150,7 @@
public void resetSafely(long now) {
mDurations.resetTable();
mStartTime = now;
+ mProcesses.removeIf(p -> !p.isInUse());
}
/**
diff --git a/core/java/com/android/internal/jank/EventLogTags.logtags b/core/java/com/android/internal/jank/EventLogTags.logtags
index 7af5d8f..ad47b81 100644
--- a/core/java/com/android/internal/jank/EventLogTags.logtags
+++ b/core/java/com/android/internal/jank/EventLogTags.logtags
@@ -3,8 +3,8 @@
option java_package com.android.internal.jank;
# Marks a request to start tracing a CUJ. Doesn't mean the request was executed.
-37001 jank_cuj_events_begin_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Ns|2|3)
+37001 jank_cuj_events_begin_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Ns|2|3)
# Marks a request to end tracing a CUJ. Doesn't mean the request was executed.
-37002 jank_cuj_events_end_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
+37002 jank_cuj_events_end_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
# Marks a request to cancel tracing a CUJ. Doesn't mean the request was executed.
-37003 jank_cuj_events_cancel_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
+37003 jank_cuj_events_cancel_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 62f1599..7ae63b1 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -37,6 +37,7 @@
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
@@ -127,6 +128,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.Instant;
import java.util.Locale;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -240,6 +242,7 @@
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
public static final int CUJ_IME_INSETS_ANIMATION = 69;
+ public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
private static final int NO_STATSD_LOGGING = -1;
@@ -318,6 +321,7 @@
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION,
+ UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION,
};
private static class InstanceHolder {
@@ -412,6 +416,7 @@
CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
CUJ_IME_INSETS_ANIMATION,
+ CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -574,8 +579,10 @@
public boolean begin(@NonNull Configuration.Builder builder) {
try {
final Configuration config = builder.build();
- EventLogTags.writeJankCujEventsBeginRequest(
- config.mCujType, SystemClock.elapsedRealtimeNanos(), SystemClock.uptimeNanos());
+ postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+ EventLogTags.writeJankCujEventsBeginRequest(
+ config.mCujType, unixNanos, elapsedNanos, realtimeNanos);
+ });
final TrackerResult result = new TrackerResult();
final boolean success = config.getHandler().runWithScissors(
() -> result.mResult = beginInternal(config), EXECUTOR_TASK_TIMEOUT);
@@ -649,8 +656,10 @@
* @return boolean true if the tracker is ended successfully, false otherwise.
*/
public boolean end(@CujType int cujType) {
- EventLogTags.writeJankCujEventsEndRequest(cujType, SystemClock.elapsedRealtimeNanos(),
- SystemClock.uptimeNanos());
+ postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+ EventLogTags.writeJankCujEventsEndRequest(
+ cujType, unixNanos, elapsedNanos, realtimeNanos);
+ });
FrameTracker tracker = getTracker(cujType);
// Skip this call since we haven't started a trace yet.
if (tracker == null) return false;
@@ -688,8 +697,10 @@
* @return boolean true if the tracker is cancelled successfully, false otherwise.
*/
public boolean cancel(@CujType int cujType) {
- EventLogTags.writeJankCujEventsCancelRequest(cujType, SystemClock.elapsedRealtimeNanos(),
- SystemClock.uptimeNanos());
+ postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+ EventLogTags.writeJankCujEventsCancelRequest(
+ cujType, unixNanos, elapsedNanos, realtimeNanos);
+ });
return cancel(cujType, REASON_CANCEL_NORMAL);
}
@@ -946,6 +957,8 @@
return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
case CUJ_IME_INSETS_ANIMATION:
return "IME_INSETS_ANIMATION";
+ case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION:
+ return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
}
return "UNKNOWN";
}
@@ -1278,4 +1291,21 @@
return mReason;
}
}
+
+ @FunctionalInterface
+ private interface TimeFunction {
+ void invoke(long unixNanos, long elapsedNanos, long realtimeNanos);
+ }
+
+ private void postEventLogToWorkerThread(TimeFunction logFunction) {
+ final Instant now = Instant.now();
+ final long unixNanos = TimeUnit.NANOSECONDS.convert(now.getEpochSecond(), TimeUnit.SECONDS)
+ + now.getNano();
+ final long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+ final long realtimeNanos = SystemClock.uptimeNanos();
+
+ mWorker.getThreadHandler().post(() -> {
+ logFunction.invoke(unixNanos, elapsedNanos, realtimeNanos);
+ });
+ }
}
diff --git a/core/java/com/android/internal/midi/EventScheduler.java b/core/java/com/android/internal/midi/EventScheduler.java
index 506902f6..426cd74 100644
--- a/core/java/com/android/internal/midi/EventScheduler.java
+++ b/core/java/com/android/internal/midi/EventScheduler.java
@@ -16,7 +16,6 @@
package com.android.internal.midi;
-import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -26,11 +25,11 @@
* And only one Thread can read from the buffer.
*/
public class EventScheduler {
- private static final long NANOS_PER_MILLI = 1000000;
+ public static final long NANOS_PER_MILLI = 1000000;
private final Object mLock = new Object();
- volatile private SortedMap<Long, FastEventQueue> mEventBuffer;
- private FastEventQueue mEventPool = null;
+ protected volatile SortedMap<Long, FastEventQueue> mEventBuffer;
+ protected FastEventQueue mEventPool = null;
private int mMaxPoolSize = 200;
private boolean mClosed;
@@ -38,9 +37,13 @@
mEventBuffer = new TreeMap<Long, FastEventQueue>();
}
- // If we keep at least one node in the list then it can be atomic
- // and non-blocking.
- private class FastEventQueue {
+ /**
+ * Class for a fast event queue.
+ *
+ * If we keep at least one node in the list then it can be atomic
+ * and non-blocking.
+ */
+ public static class FastEventQueue {
// One thread takes from the beginning of the list.
volatile SchedulableEvent mFirst;
// A second thread returns events to the end of the list.
@@ -48,7 +51,7 @@
volatile long mEventsAdded;
volatile long mEventsRemoved;
- FastEventQueue(SchedulableEvent event) {
+ public FastEventQueue(SchedulableEvent event) {
mFirst = event;
mLast = mFirst;
mEventsAdded = 1;
@@ -149,7 +152,8 @@
* @param event
*/
public void add(SchedulableEvent event) {
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
FastEventQueue list = mEventBuffer.get(event.getTimestamp());
if (list == null) {
long lowestTime = mEventBuffer.isEmpty() ? Long.MAX_VALUE
@@ -159,7 +163,7 @@
// If the event we added is earlier than the previous earliest
// event then notify any threads waiting for the next event.
if (event.getTimestamp() < lowestTime) {
- mLock.notify();
+ lock.notify();
}
} else {
list.add(event);
@@ -167,7 +171,7 @@
}
}
- private SchedulableEvent removeNextEventLocked(long lowestTime) {
+ protected SchedulableEvent removeNextEventLocked(long lowestTime) {
SchedulableEvent event;
FastEventQueue list = mEventBuffer.get(lowestTime);
// Remove list from tree if this is the last node.
@@ -186,7 +190,8 @@
*/
public SchedulableEvent getNextEvent(long time) {
SchedulableEvent event = null;
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
if (!mEventBuffer.isEmpty()) {
long lowestTime = mEventBuffer.firstKey();
// Is it time for this list to be processed?
@@ -209,7 +214,8 @@
*/
public SchedulableEvent waitNextEvent() throws InterruptedException {
SchedulableEvent event = null;
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
while (!mClosed) {
long millisToWait = Integer.MAX_VALUE;
if (!mEventBuffer.isEmpty()) {
@@ -231,7 +237,7 @@
}
}
}
- mLock.wait((int) millisToWait);
+ lock.wait((int) millisToWait);
}
}
return event;
@@ -242,10 +248,25 @@
mEventBuffer = new TreeMap<Long, FastEventQueue>();
}
+ /**
+ * Stops the EventScheduler.
+ * The subscriber calling waitNextEvent() will get one final SchedulableEvent returning null.
+ */
public void close() {
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
mClosed = true;
- mLock.notify();
+ lock.notify();
}
}
+
+ /**
+ * Gets the lock. This doesn't lock it in anyway.
+ * Subclasses can override this.
+ *
+ * @return Object
+ */
+ protected Object getLock() {
+ return mLock;
+ }
}
diff --git a/core/java/com/android/internal/midi/MidiEventMultiScheduler.java b/core/java/com/android/internal/midi/MidiEventMultiScheduler.java
new file mode 100644
index 0000000..16e4abe
--- /dev/null
+++ b/core/java/com/android/internal/midi/MidiEventMultiScheduler.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.midi;
+
+/**
+ * Uses multiple MidiEventSchedulers for waiting for events.
+ *
+ */
+public class MidiEventMultiScheduler {
+ private MultiLockMidiEventScheduler[] mMidiEventSchedulers;
+ private int mNumEventSchedulers;
+ private int mNumClosedSchedulers = 0;
+ private final Object mMultiLock = new Object();
+
+ private class MultiLockMidiEventScheduler extends MidiEventScheduler {
+ @Override
+ public void close() {
+ synchronized (mMultiLock) {
+ mNumClosedSchedulers++;
+ }
+ super.close();
+ }
+
+ @Override
+ protected Object getLock() {
+ return mMultiLock;
+ }
+
+ public boolean isEventBufferEmptyLocked() {
+ return mEventBuffer.isEmpty();
+ }
+
+ public long getLowestTimeLocked() {
+ return mEventBuffer.firstKey();
+ }
+ }
+
+ /**
+ * MidiEventMultiScheduler constructor
+ *
+ * @param numSchedulers the number of schedulers to create
+ */
+ public MidiEventMultiScheduler(int numSchedulers) {
+ mNumEventSchedulers = numSchedulers;
+ mMidiEventSchedulers = new MultiLockMidiEventScheduler[numSchedulers];
+ for (int i = 0; i < numSchedulers; i++) {
+ mMidiEventSchedulers[i] = new MultiLockMidiEventScheduler();
+ }
+ }
+
+ /**
+ * Waits for the next MIDI event. This will return true when it receives it.
+ * If all MidiEventSchedulers have been closed, this will return false.
+ *
+ * @return true if a MIDI event is received and false if all schedulers are closed.
+ */
+ public boolean waitNextEvent() throws InterruptedException {
+ synchronized (mMultiLock) {
+ while (true) {
+ if (mNumClosedSchedulers >= mNumEventSchedulers) {
+ return false;
+ }
+ long lowestTime = Long.MAX_VALUE;
+ long now = System.nanoTime();
+ for (MultiLockMidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+ if (!eventScheduler.isEventBufferEmptyLocked()) {
+ lowestTime = Math.min(lowestTime,
+ eventScheduler.getLowestTimeLocked());
+ }
+ }
+ if (lowestTime <= now) {
+ return true;
+ }
+ long nanosToWait = lowestTime - now;
+ // Add 1 millisecond so we don't wake up before it is
+ // ready.
+ long millisToWait = 1 + (nanosToWait / EventScheduler.NANOS_PER_MILLI);
+ // Clip 64-bit value to 32-bit max.
+ if (millisToWait > Integer.MAX_VALUE) {
+ millisToWait = Integer.MAX_VALUE;
+ }
+ mMultiLock.wait(millisToWait);
+ }
+ }
+ }
+
+ /**
+ * Gets the number of MidiEventSchedulers.
+ *
+ * @return the number of MidiEventSchedulers.
+ */
+ public int getNumEventSchedulers() {
+ return mNumEventSchedulers;
+ }
+
+ /**
+ * Gets a specific MidiEventScheduler based on the index.
+ *
+ * @param index the zero indexed index of a MIDI event scheduler
+ * @return a MidiEventScheduler
+ */
+ public MidiEventScheduler getEventScheduler(int index) {
+ return mMidiEventSchedulers[index];
+ }
+
+ /**
+ * Closes all event schedulers.
+ */
+ public void close() {
+ for (MidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+ eventScheduler.close();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/midi/MidiEventScheduler.java b/core/java/com/android/internal/midi/MidiEventScheduler.java
index 7b01904..1b2934d 100644
--- a/core/java/com/android/internal/midi/MidiEventScheduler.java
+++ b/core/java/com/android/internal/midi/MidiEventScheduler.java
@@ -79,7 +79,7 @@
/**
* Create an event that contains the message.
*/
- private MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
+ public MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
long timestamp) {
MidiEvent event;
if (count > POOL_EVENT_SIZE) {
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 65655b7..70514c3 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -80,10 +80,6 @@
/** Stores user time and system time in jiffies. */
private final long[] mProcessStatsData = new long[4];
- /** Stores user time and system time in jiffies. Used for
- * public API to retrieve CPU use for a process. Must lock while in use. */
- private final long[] mSinglePidStatsData = new long[4];
-
private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
PROC_SPACE_TERM,
PROC_SPACE_TERM|PROC_PARENS|PROC_OUT_STRING, // 2: name
@@ -629,17 +625,15 @@
* executing in both user and system code. Safe to call without lock held.
*/
public long getCpuTimeForPid(int pid) {
- synchronized (mSinglePidStatsData) {
- final String statFile = "/proc/" + pid + "/stat";
- final long[] statsData = mSinglePidStatsData;
- if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
- null, statsData, null)) {
- long time = statsData[PROCESS_STAT_UTIME]
+ final String statFile = "/proc/" + pid + "/stat";
+ final long[] statsData = new long[4];
+ if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
+ null, statsData, null)) {
+ long time = statsData[PROCESS_STAT_UTIME]
+ statsData[PROCESS_STAT_STIME];
- return time * mJiffyMillis;
- }
- return 0;
+ return time * mJiffyMillis;
}
+ return 0;
}
/**
@@ -647,15 +641,13 @@
* in the runqueue. Safe to call without lock held.
*/
public long getCpuDelayTimeForPid(int pid) {
- synchronized (mSinglePidStatsData) {
- final String statFile = "/proc/" + pid + "/schedstat";
- final long[] statsData = mSinglePidStatsData;
- if (Process.readProcFile(statFile, PROCESS_SCHEDSTATS_FORMAT,
- null, statsData, null)) {
- return statsData[PROCESS_SCHEDSTAT_CPU_DELAY_TIME] / 1_000_000;
- }
- return 0;
+ final String statFile = "/proc/" + pid + "/schedstat";
+ final long[] statsData = new long[4];
+ if (Process.readProcFile(statFile, PROCESS_SCHEDSTATS_FORMAT,
+ null, statsData, null)) {
+ return statsData[PROCESS_SCHEDSTAT_CPU_DELAY_TIME] / 1_000_000;
}
+ return 0;
}
/**
diff --git a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
index cd55d32..f2b0544 100644
--- a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
@@ -259,6 +259,7 @@
if (writeToFile) {
writeProtoLogToFileLocked();
logAndPrintln(pw, "Log written to " + mLogFile + ".");
+ mBuffer.resetBuffer();
}
if (mProtoLogEnabled) {
logAndPrintln(pw, "ERROR: logging was re-enabled while waiting for flush.");
diff --git a/core/proto/android/nfc/Android.bp b/core/proto/android/nfc/Android.bp
new file mode 100644
index 0000000..6a62c91
--- /dev/null
+++ b/core/proto/android/nfc/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+ name: "srcs_nfc_proto",
+ srcs: [
+ "*.proto",
+ ],
+}
+
+// Will be statically linked by `framework-nfc`.
+java_library {
+ name: "nfc-proto-java-gen",
+ installable: false,
+ proto: {
+ type: "stream",
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ },
+ srcs: [
+ ":srcs_nfc_proto",
+ ],
+ sdk_version: "current",
+ min_sdk_version: "current",
+}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 8caf127..a5d287c 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -95,6 +95,8 @@
optional SettingProto hearing_aid_media_routing = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto hearing_aid_system_sounds_routing = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_magnification_joystick_enabled = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Settings for font scaling
+ optional SettingProto accessibility_font_scaling_has_been_changed = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Accessibility accessibility = 2;
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index e029af4..f87d910 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -285,22 +285,24 @@
repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
}
+// Enum used in DNDModeProto to specify the zen mode setting.
+enum LoggedZenMode {
+ ROOT_CONFIG = -1; // Used to distinguish config (one per user) from the rules.
+ OFF = 0;
+ IMPORTANT_INTERRUPTIONS = 1;
+ NO_INTERRUPTIONS = 2;
+ ALARMS = 3;
+}
+
/**
* Atom that represents an item in the list of Do Not Disturb rules, pulled from
* NotificationManagerService.java.
*/
message DNDModeProto {
- enum Mode {
- ROOT_CONFIG = -1; // Used to distinguish the config (one per user) from the rules.
- ZEN_MODE_OFF = 0;
- ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
- ZEN_MODE_NO_INTERRUPTIONS = 2;
- ZEN_MODE_ALARMS = 3;
- }
optional int32 user = 1; // Android user ID (0, 1, 10, ...)
optional bool enabled = 2; // true for ROOT_CONFIG if a manualRule is enabled
optional bool channels_bypassing = 3; // only valid for ROOT_CONFIG
- optional Mode zen_mode = 4;
+ optional LoggedZenMode zen_mode = 4;
// id is one of the system default rule IDs, or empty
// May also be "MANUAL_RULE" to indicate app-activation of the manual rule.
optional string id = 5;
@@ -308,15 +310,34 @@
optional DNDPolicyProto policy = 7;
}
+// Enum used in DNDPolicyProto for a particular policy parameter's state.
+enum State {
+ STATE_UNSET = 0;
+ STATE_ALLOW = 1;
+ STATE_DISALLOW = 2;
+}
+
+// Enum used in DNDPolicyProto for which people are allowed to break through.
+enum PeopleType {
+ PEOPLE_UNSET = 0;
+ PEOPLE_ANYONE = 1;
+ PEOPLE_CONTACTS = 2;
+ PEOPLE_STARRED = 3;
+ PEOPLE_NONE = 4;
+}
+
+// Enum used in DNDPolicyProto for conversation types allowed to break through.
+enum ConversationType {
+ CONV_UNSET = 0;
+ CONV_ANYONE = 1;
+ CONV_IMPORTANT = 2;
+ CONV_NONE = 3;
+}
+
/**
- * Atom that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
+ * Message that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
*/
message DNDPolicyProto {
- enum State {
- STATE_UNSET = 0;
- STATE_ALLOW = 1;
- STATE_DISALLOW = 2;
- }
optional State calls = 1;
optional State repeat_callers = 2;
optional State messages = 3;
@@ -334,23 +355,8 @@
optional State ambient = 15;
optional State notification_list = 16;
- enum PeopleType {
- PEOPLE_UNSET = 0;
- PEOPLE_ANYONE = 1;
- PEOPLE_CONTACTS = 2;
- PEOPLE_STARRED = 3;
- PEOPLE_NONE = 4;
- }
-
optional PeopleType allow_calls_from = 17;
optional PeopleType allow_messages_from = 18;
- enum ConversationType {
- CONV_UNSET = 0;
- CONV_ANYONE = 1;
- CONV_IMPORTANT = 2;
- CONV_NONE = 3;
- }
-
optional ConversationType allow_conversations_from = 19;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 85d1765..b736230 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3707,7 +3707,8 @@
<!-- @SystemApi @hide Allows an application to set a device owner on retail demo devices.-->
<permission android:name="android.permission.PROVISION_DEMO_DEVICE"
- android:protectionLevel="signature|setup" />
+ android:protectionLevel="signature|setup|knownSigner"
+ android:knownCerts="@array/demo_device_provisioning_known_signers" />
<!-- @TestApi @hide Allows an application to reset the record of previous system update freeze
periods. -->
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 76b39bb..70464d8 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -207,12 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Aplikazio pertsonalak blokeatuta egongo dira laneko profila aktibatzen duzun arte"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikazio pertsonalak egun eta ordu honetan blokeatuko dira: <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. IKT saileko administratzaileak ez dizu ematen baimenik laneko profila <xliff:g id="NUMBER">%3$d</xliff:g> egunez baino gehiagoz desaktibatuta edukitzeko."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktibatu"</string>
- <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
- <skip />
- <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
- <skip />
- <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
- <skip />
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Deiak eta mezuak desaktibatuta daude"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Laneko aplikazioak pausatu dituzu. Ez duzu jasoko telefono-deirik edo testu-mezurik."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Berraktibatu laneko aplikazioak"</string>
<string name="me" msgid="6207584824693813140">"Ni"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletaren aukerak"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV gailuaren aukerak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index dfb0b2e..562560e 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -296,7 +296,7 @@
<string name="safeMode" msgid="8974401416068943888">"حالت ایمن"</string>
<string name="android_system_label" msgid="5974767339591067210">"سیستم Android"</string>
<string name="user_owner_label" msgid="8628726904184471211">"جابهجا شدن به نمایه شخصی"</string>
- <string name="managed_profile_label" msgid="7316778766973512382">"جابهجا شدن به نمایه کاری"</string>
+ <string name="managed_profile_label" msgid="7316778766973512382">"رفتن به نمایه کاری"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"مخاطبین"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"دسترسی به مخاطبین شما"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"مکان"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 0c4dfae..b8a364b 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -208,12 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vos applications personnelles sont bloquées jusqu\'à ce que vous activiez votre profil professionnel"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Les applications personnelles seront bloquées le <xliff:g id="DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>. Votre administrateur informatique ne vous autorise pas à laisser votre profil professionnel désactivé pendant plus de <xliff:g id="NUMBER">%3$d</xliff:g> jours."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activer"</string>
- <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
- <skip />
- <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
- <skip />
- <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
- <skip />
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Les appels et messages sont désactivés"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Vous avez mis en pause les applications professionnelles. Vous ne recevrez aucun appel téléphonique ni message texte."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Réact. applis prof."</string>
<string name="me" msgid="6207584824693813140">"Moi"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Options d\'Android TV"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 706e920..7169464 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1960,7 +1960,7 @@
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string>
<string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Անհրաժեշտ է թույլտվություն"</string>
<string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Տեսախցիկն անհասանելի է"</string>
- <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարունակեք հեռախոսով"</string>
+ <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարունակեք հեռախոսով"</string>
<string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Խոսափողն անհասանելի է"</string>
<string name="app_streaming_blocked_title_for_playstore_dialog" msgid="8149823099822897538">"Play Խանութը հասանելի չէ"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ի կարգավորումներն անհասանելի են"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bd29ffb..a587864 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1985,7 +1985,7 @@
<string name="profile_encrypted_message" msgid="1128512616293157802">"Tocca per sbloc. prof. di lav."</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connesso a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tocca per visualizzare i file"</string>
- <string name="pin_target" msgid="8036028973110156895">"Blocca"</string>
+ <string name="pin_target" msgid="8036028973110156895">"Fissa"</string>
<string name="pin_specific_target" msgid="7824671240625957415">"Blocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Sgancia"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Sblocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8064eb0..348dcd5 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -207,12 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"직장 프로필을 사용 설정할 때까지 개인 앱이 차단됩니다."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"개인 앱이 <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>에 차단됩니다. IT 관리자가 <xliff:g id="NUMBER">%3$d</xliff:g>일 넘게 직장 프로필을 중지하도록 허용하지 않습니다."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"사용 설정"</string>
- <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
- <skip />
- <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
- <skip />
- <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
- <skip />
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"전화 및 메시지 사용 중지됨"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"직장 앱을 일시중지했습니다. 전화나 문자 메시지를 수신하지 않습니다."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"직장 앱 일시중지 해제"</string>
<string name="me" msgid="6207584824693813140">"나"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"태블릿 옵션"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 옵션"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 3888e0c..047d126 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1172,8 +1172,8 @@
<string name="no" msgid="5122037903299899715">"Отмена"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"Внимание!"</string>
<string name="loading" msgid="3138021523725055037">"Загрузка…"</string>
- <string name="capital_on" msgid="2770685323900821829">"I"</string>
- <string name="capital_off" msgid="7443704171014626777">"O"</string>
+ <string name="capital_on" msgid="2770685323900821829">"Включено"</string>
+ <string name="capital_off" msgid="7443704171014626777">"Выключено"</string>
<string name="checked" msgid="9179896827054513119">"отмечено"</string>
<string name="not_checked" msgid="7972320087569023342">"не отмечено"</string>
<string name="selected" msgid="6614607926197755875">"выбрано"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 4468ebe..b35481d 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -227,4 +227,10 @@
<string-array name="device_state_notification_thermal_contents">
<item>@string/concurrent_display_notification_thermal_content</item>
</string-array>
+
+ <!-- Certificate digests for trusted apps that will be allowed to obtain the knownSigner of the
+ demo device provisioning permissions. -->
+ <string-array name="demo_device_provisioning_known_signers">
+ <item>@string/config_retailDemoPackageSignature</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f92b344..a21009f2f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3201,8 +3201,8 @@
<!-- Describes whether this view should allow interactions from AccessibilityServices only
if the service sets the isAccessibilityTool property. -->
- <attr name="accessibilityDataPrivate" format="integer">
- <!-- The system determines whether the view's accessibility data is private
+ <attr name="accessibilityDataSensitive" format="integer">
+ <!-- The system determines whether the view's accessibility data is sensitive
- default (recommended). -->
<enum name="auto" value="0" />
<!-- Allow interactions from AccessibilityServices only if the service sets the
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 209c785..ffb602d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1158,14 +1158,25 @@
<integer name="config_triplePressOnStemPrimaryBehavior">0</integer>
<!-- Control the behavior when the user short presses the stem primary button.
- Stem primary button is only used on watch form factor. If a device is not
- a watch, setting this config is no-op.
- 0 - Nothing
- 1 - Go to launch all apps
+ Stem primary button is only used on watch form factor. If a device is not
+ a watch, setting this config is no-op.
+ 0 - Nothing
+ 1 - Go to launch all apps
-->
<integer name="config_shortPressOnStemPrimaryBehavior">0</integer>
+ <!-- Control the behavior of the search key.
+ 0 - Launch default search activity
+ 1 - Launch target activity defined by config_searchKeyTargetActivity
+ -->
+ <integer name="config_searchKeyBehavior">0</integer>
+
+ <!-- Component name for the default target activity to be launched when user
+ presses the global search key. [DO NOT TRANSLATE]
+ -->
+ <string name="config_searchKeyTargetActivity" translatable="false"></string>
+
<!-- Time to wait while a button is pressed before triggering a very long press. -->
<integer name="config_veryLongPressTimeout">3500</integer>
@@ -2787,8 +2798,10 @@
<integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->
<!-- Whether the main user is a permanent admin user. If the main user is a permanent admin user
- it can't be deleted or downgraded to non-admin status. -->
- <bool name="config_isMainUserPermanentAdmin">false</bool>
+ it can't be deleted or downgraded to non-admin status.
+ This is generally only relevant on headless system user mode devices; on other devices, the
+ main user is the system user which is always a permanent admin anyway. -->
+ <bool name="config_isMainUserPermanentAdmin">true</bool>
<!-- Whether switch to headless system user is allowed. If allowed,
headless system user can run in the foreground even though it is not a full user. -->
@@ -3975,7 +3988,7 @@
<!-- Whether the device supports non-resizable activity in multi windowing modes.
-1: The device doesn't support non-resizable in multi windowing modes.
0: The device supports non-resizable in multi windowing modes only if this is a large
- screen (smallest width >= {@link config_largeScreenSmallestScreenWidthDp}).
+ screen (smallest width >= {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}).
1: The device always supports non-resizable in multi windowing modes.
-->
<integer name="config_supportsNonResizableMultiWindow">0</integer>
@@ -3985,9 +3998,9 @@
-1: The device ignores the activity min width/height when determining if it can be shown in
multi windowing modes.
0: If this is a small screen (smallest width <
- {@link config_largeScreenSmallestScreenWidthDp}), the device compares the activity min
- width/height with the min multi windowing modes dimensions the device supports to
- determine if the activity can be shown in multi windowing modes
+ {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}), the device compares the
+ activity min width/height with the min multi windowing modes dimensions the device
+ supports to determine if the activity can be shown in multi windowing modes
1: The device always compare the activity min width/height with the min multi windowing
modes dimensions {@link config_minPercentageMultiWindowSupportWidth} the device
supports to determine if the activity can be shown in multi windowing modes.
@@ -4010,11 +4023,6 @@
-->
<item name="config_minPercentageMultiWindowSupportWidth" format="float" type="dimen">0.5</item>
- <!-- If the display smallest screen width is greater or equal to this value, we will treat it
- as a large screen device, which will have some multi window features enabled by default.
- -->
- <integer name="config_largeScreenSmallestScreenWidthDp">600</integer>
-
<!-- True if the device is using legacy split. -->
<bool name="config_useLegacySplit">false</bool>
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 24a7d85..ebda172 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -110,6 +110,10 @@
<string name="config_satellite_service_package" translatable="false"></string>
<java-symbol type="string" name="config_satellite_service_package" />
+ <!-- Telephony pointing UI package name to be launched. -->
+ <string name="config_pointing_ui_package" translatable="false"></string>
+ <java-symbol type="string" name="config_pointing_ui_package" />
+
<!-- Whether enhanced IWLAN handover check is enabled. If enabled, telephony frameworks
will not perform handover if the target transport is out of service, or VoPS not
supported. The network will be torn down on the source transport, and will be
@@ -119,7 +123,7 @@
<java-symbol type="bool" name="config_enhanced_iwlan_handover_check" />
<!-- Whether using the new SubscriptionManagerService or the old SubscriptionController -->
- <bool name="config_using_subscription_manager_service">false</bool>
+ <bool name="config_using_subscription_manager_service">true</bool>
<java-symbol type="bool" name="config_using_subscription_manager_service" />
<!-- Whether asynchronously update the subscription database or not. Async mode increases
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index ee02100..69d5fef 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -114,7 +114,7 @@
<public name="handwritingBoundsOffsetTop" />
<public name="handwritingBoundsOffsetRight" />
<public name="handwritingBoundsOffsetBottom" />
- <public name="accessibilityDataPrivate" />
+ <public name="accessibilityDataSensitive" />
<public name="enableTextStylingShortcuts" />
<public name="requiredDisplayCategory"/>
<public name="removed_maxConcurrentSessionsCount" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8d56e7a..92dc569 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -405,7 +405,6 @@
<java-symbol type="integer" name="config_respectsActivityMinWidthHeightMultiWindow" />
<java-symbol type="dimen" name="config_minPercentageMultiWindowSupportHeight" />
<java-symbol type="dimen" name="config_minPercentageMultiWindowSupportWidth" />
- <java-symbol type="integer" name="config_largeScreenSmallestScreenWidthDp" />
<java-symbol type="bool" name="config_useLegacySplit" />
<java-symbol type="bool" name="config_noHomeScreen" />
<java-symbol type="bool" name="config_supportsSystemDecorsOnSecondaryDisplays" />
@@ -464,6 +463,8 @@
<java-symbol type="integer" name="config_doublePressOnStemPrimaryBehavior" />
<java-symbol type="integer" name="config_triplePressOnStemPrimaryBehavior" />
<java-symbol type="string" name="config_doublePressOnPowerTargetActivity" />
+ <java-symbol type="integer" name="config_searchKeyBehavior" />
+ <java-symbol type="string" name="config_searchKeyTargetActivity" />
<java-symbol type="integer" name="config_windowOutsetBottom" />
<java-symbol type="integer" name="db_connection_pool_size" />
<java-symbol type="integer" name="db_journal_size_limit" />
diff --git a/core/res/res/xml/irq_device_map.xml b/core/res/res/xml/irq_device_map.xml
index 86a44d6..4fae8fb 100644
--- a/core/res/res/xml/irq_device_map.xml
+++ b/core/res/res/xml/irq_device_map.xml
@@ -17,14 +17,15 @@
*/
-->
<irq-device-map>
- <!-- This file maps devices (chips) that can send IRQs to the CPU (and bring it out of sleep) to
- logical subsystems in userspace code. Since each Android device has its own uniquely
- designed chipset, this mapping is expected to be empty by default and should be overridden
- by device specific configs.
+ <!-- This file maps devices (chips) that can send interrupts to the main processor (and bring it
+ out of sleep) to logical subsystems in userspace code. Since each Android device has its own
+ uniquely designed chipset, this mapping is expected to be empty by default and should be
+ overridden by device-specific configs.
This mapping helps the system to meaningfully attribute CPU wakeups to logical work that
happened on the device. The devices are referred to by their names as defined in the kernel.
- Currently defined subsystems are:
+ Currently, defined subsystems are:
- Alarm: Use this to denote wakeup alarms requested by apps via the AlarmManager API.
+ - Wifi: Use this to denote network traffic that uses the wifi transport.
The overlay should use tags <device> and <subsystem> to describe this mapping in the
following way:
diff --git a/core/tests/coretests/src/android/content/pm/UserPackageTest.java b/core/tests/coretests/src/android/content/pm/UserPackageTest.java
new file mode 100644
index 0000000..5114e2cf
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/UserPackageTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.platform.test.annotations.Presubmit;
+
+import junit.framework.TestCase;
+
+@Presubmit
+public class UserPackageTest extends TestCase {
+ public void testCacheLimit() {
+ UserPackage.setValidUserIds(new int[]{0});
+ for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+ UserPackage.of(0, "app" + i);
+ assertEquals(i + 1, UserPackage.numEntriesForUser(0));
+ }
+
+ for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+ UserPackage.of(0, "appOverLimit" + i);
+ final int numCached = UserPackage.numEntriesForUser(0);
+ assertTrue(numCached >= 1);
+ assertTrue(numCached <= UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index ee1b2aa..e48f8a0 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -132,9 +132,13 @@
}
.forEach { (table, sp) ->
try {
- assertWithMessage("convertSpToDp(%s) on table: %s", sp, table)
- .that(table.convertSpToDp(sp))
- .isFinite()
+ // Truth is slow because it creates a bunch of
+ // objects. Don't use it unless we need to.
+ if (!table.convertSpToDp(sp).isFinite()) {
+ assertWithMessage("convertSpToDp(%s) on table: %s", sp, table)
+ .that(table.convertSpToDp(sp))
+ .isFinite()
+ }
} catch (e: Exception) {
throw AssertionError("Exception during convertSpToDp($sp) on table: $table", e)
}
diff --git a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
index 25664fb..43334ab 100644
--- a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
+++ b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
@@ -101,8 +101,9 @@
mGetRequest = new GetCredentialRequest.Builder(Bundle.EMPTY).addCredentialOption(
new CredentialOption(Credential.TYPE_PASSWORD_CREDENTIAL, Bundle.EMPTY,
Bundle.EMPTY, false)).build();
- mCreateRequest = new CreateCredentialRequest.Builder(Bundle.EMPTY, Bundle.EMPTY)
- .setType(Credential.TYPE_PASSWORD_CREDENTIAL)
+ mCreateRequest = new CreateCredentialRequest.Builder(
+ Credential.TYPE_PASSWORD_CREDENTIAL,
+ Bundle.EMPTY, Bundle.EMPTY)
.setIsSystemProviderRequired(false)
.setAlwaysSendAppInfoToProvider(false)
.build();
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 1db6587..6fa8f11 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -19,6 +19,7 @@
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.LAST;
import static android.view.WindowInsets.Type.SIZE;
+import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
@@ -51,11 +52,13 @@
private final InsetsSource mSource = new InsetsSource(0 /* id */, navigationBars());
private final InsetsSource mImeSource = new InsetsSource(1 /* id */, ime());
+ private final InsetsSource mCaptionSource = new InsetsSource(2 /* id */, captionBar());
@Before
public void setUp() {
mSource.setVisible(true);
mImeSource.setVisible(true);
+ mCaptionSource.setVisible(true);
}
@Test
@@ -107,6 +110,17 @@
}
@Test
+ public void testCalculateInsets_caption_resizing() {
+ mCaptionSource.setFrame(new Rect(0, 0, 100, 100));
+ Insets insets = mCaptionSource.calculateInsets(new Rect(0, 0, 200, 200), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ insets = mCaptionSource.calculateInsets(new Rect(0, 0, 50, 200), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ insets = mCaptionSource.calculateInsets(new Rect(100, 100, 200, 500), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
public void testCalculateInsets_invisible() {
mSource.setFrame(new Rect(0, 0, 500, 100));
mSource.setVisible(false);
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index b035c23..fde1a6d 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -248,6 +248,18 @@
}
@Test
+ public void testCalculateInsets_captionBarOffset() {
+ mState.getOrCreateSource(ID_CAPTION_BAR, captionBar())
+ .setFrame(new Rect(0, 0, 100, 300))
+ .setVisible(true);
+
+ Insets visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
+ assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
+ }
+
+ @Test
public void testCalculateInsets_extraNavRightStatusTop() {
mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
.setFrame(new Rect(0, 0, 100, 100))
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 6d635af..3d4918b 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -58,7 +58,7 @@
// The number of flags held in boolean properties. Their values should also be double-checked
// in the methods above.
- private static final int NUM_BOOLEAN_PROPERTIES = 26;
+ private static final int NUM_BOOLEAN_PROPERTIES = 27;
@Test
public void testStandardActions_serializationFlagIsValid() {
diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
index 9b9a84b..35b3267 100644
--- a/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
@@ -156,4 +156,19 @@
eq(0),
eq(APP_1_PROCESS_NAME));
}
+
+ @SmallTest
+ public void testSafelyResetClearsProcessInUidState() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ ProcessState processState =
+ processStats.getProcessStateLocked(
+ APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+ processState.makeActive();
+ UidState uidState = processStats.mUidStates.get(APP_1_UID);
+ assertTrue(uidState.isInUse());
+ processState.makeInactive();
+ uidState.resetSafely(NOW_MS);
+ processState.makeActive();
+ assertFalse(uidState.isInUse());
+ }
}
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 539eb62..be2c27d 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -51,6 +51,7 @@
import android.app.LoadedApk;
import android.app.servertransaction.PendingTransactionActions;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -293,7 +294,7 @@
private Activity launchActivity(ActivityClientRecord r) {
return mThread.handleLaunchActivity(r, null /* pendingActions */,
- null /* customIntent */);
+ Context.DEVICE_ID_DEFAULT, null /* customIntent */);
}
private void startActivity(ActivityClientRecord r) {
@@ -347,7 +348,7 @@
doNothing().when(packageInfo).updateApplicationInfo(any(), any());
return new ActivityClientRecord(mock(IBinder.class), Intent.makeMainActivity(component),
- 0 /* ident */, info, new Configuration(), 0 /*deviceId */, null /* referrer */,
+ 0 /* ident */, info, new Configuration(), null /* referrer */,
null /* voiceInteractor */, null /* state */, null /* persistentState */,
null /* pendingResults */, null /* pendingNewIntents */,
null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
diff --git a/core/tests/overlaytests/device/Android.bp b/core/tests/overlaytests/device/Android.bp
index 0d3b15a..2b22344 100644
--- a/core/tests/overlaytests/device/Android.bp
+++ b/core/tests/overlaytests/device/Android.bp
@@ -29,6 +29,7 @@
static_libs: [
"androidx.test.rules",
"testng",
+ "compatibility-device-util-axt",
],
test_suites: ["device-tests"],
data: [
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index 8e4b9ef..fcf71ed 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -37,10 +37,12 @@
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.AmUtils;
import com.android.internal.util.ArrayUtils;
import com.android.overlaytest.view.TestTextView;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
@@ -70,6 +72,13 @@
mMode = mode;
}
+ @BeforeClass
+ public static void setUpClass() {
+ // Wait for package_added broadcasts to be handled so that OverlayManagerService
+ // can update it's internal state with the new packages.
+ AmUtils.waitForBroadcastBarrier();
+ }
+
@Before
public void setUp() {
mContext = InstrumentationRegistry.getContext();
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 3d81d37..05e1772 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -271,6 +271,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "-1868518158": {
+ "message": "Pending back animation due to another animation is running",
+ "level": "WARN",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"-1868124841": {
"message": "screenOnEarly=%b, awake=%b, currentAppOrientation=%d, orientationSensorEnabled=%b, keyguardDrawComplete=%b, windowManagerDrawComplete=%b",
"level": "VERBOSE",
@@ -1549,6 +1555,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DragState.java"
},
+ "-692907078": {
+ "message": "Handling the deferred animation after transition finished",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"-677449371": {
"message": "moveTaskToRootTask: moving task=%d to rootTaskId=%d toTop=%b",
"level": "DEBUG",
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index a39dd08..8dd23b7 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2001,7 +2001,7 @@
checkPixelAccess(x, y);
final ColorSpace cs = getColorSpace();
- if (cs.equals(ColorSpace.get(ColorSpace.Named.SRGB))) {
+ if (cs == null || cs.equals(ColorSpace.get(ColorSpace.Named.SRGB))) {
return Color.valueOf(nativeGetPixel(mNativePtr, x, y));
}
// The returned value is in kRGBA_F16_SkColorType, which is packed as
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 87a8053..0f2f879 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -767,7 +767,7 @@
* Returns the alpha component encoded in the specified color long.
* The returned value is always in the range \([0..1]\).
*
- * @param color The color long whose blue channel to extract
+ * @param color The color long whose alpha channel to extract
* @return A float value in the range \([0..1]\)
*
* @see #colorSpace(long)
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index a7c508c..feedb7d 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -63,20 +63,20 @@
* as follows:
*
* First, let W be a weight parameter determining how much the gainmap will be applied.
- * W = clamp((log(H) - log(displayRatioHdr)) /
- * (log(displayRatioHdr) - log(displayRatioSdr), 0, 1)
+ * W = clamp((log(H) - log(minDisplayRatioForHdrTransition)) /
+ * (log(displayRatioForFullHdr) - log(minDisplayRatioForHdrTransition), 0, 1)
*
* Next, let L be the gainmap value in log space. We compute this from the value G that was
* sampled from the texture as follows:
- * L = mix(log(gainmapRatioMin), log(gainmapRatioMax), pow(G, gainmapGamma))
+ * L = mix(log(ratioMin), log(ratioMax), pow(G, gamma))
*
* Finally, apply the gainmap to compute D, the displayed pixel. If the base image is SDR then
* compute:
* D = (B + epsilonSdr) * exp(L * W) - epsilonHdr
- * If the base image is HDR then compute:
- * D = (B + epsilonHdr) * exp(L * (W - 1)) - epsilonSdr
*
- * In the above math, log() is a natural logarithm and exp() is natural exponentiation.
+ * In the above math, log() is a natural logarithm and exp() is natural exponentiation. The base
+ * for these functions cancels out and does not affect the result, so other bases may be used
+ * if preferred.
*/
public final class Gainmap implements Parcelable {
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 67eb117..babcfc3 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -22,7 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
-import android.os.Trace;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -476,26 +475,19 @@
@NonNull MeasuredText measuredPara,
@NonNull ParagraphConstraints constraints,
@IntRange(from = 0) int lineNumber) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "compute line break");
- long result = 0;
- try {
- result = nComputeLineBreaks(
- mNativePtr,
+ return new Result(nComputeLineBreaks(
+ mNativePtr,
- // Inputs
- measuredPara.getChars(),
- measuredPara.getNativePtr(),
- measuredPara.getChars().length,
- constraints.mFirstWidth,
- constraints.mFirstWidthLineCount,
- constraints.mWidth,
- constraints.mVariableTabStops,
- constraints.mDefaultTabStop,
- lineNumber);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- return new Result(result);
+ // Inputs
+ measuredPara.getChars(),
+ measuredPara.getNativePtr(),
+ measuredPara.getChars().length,
+ constraints.mFirstWidth,
+ constraints.mFirstWidthLineCount,
+ constraints.mWidth,
+ constraints.mVariableTabStops,
+ constraints.mDefaultTabStop,
+ lineNumber));
}
@FastNative
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 9f3c19b..caefb2e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -752,8 +752,6 @@
@GuardedBy("mLock")
void onActivityCreated(@NonNull WindowContainerTransaction wct,
@NonNull Activity launchedActivity) {
- // TODO(b/229680885): we don't support launching into primary yet because we want to always
- // launch the new activity on top.
resolveActivityToContainer(wct, launchedActivity, false /* isOnReparent */);
updateCallbackIfNecessary();
}
@@ -789,6 +787,13 @@
return true;
}
+ final TaskFragmentContainer container = getContainerWithActivity(activity);
+ if (!isOnReparent && container != null
+ && container.getTaskContainer().getTopTaskFragmentContainer() != container) {
+ // Do not resolve if the launched activity is not the top-most container in the Task.
+ return true;
+ }
+
/*
* We will check the following to see if there is any embedding rule matched:
* 1. Whether the new launched activity should always expand.
@@ -811,6 +816,13 @@
return true;
}
+ // Skip resolving the following split-rules if the launched activity has been requested
+ // to be launched into its current container.
+ if (container != null && container.isActivityInRequestedTaskFragment(
+ activity.getActivityToken())) {
+ return true;
+ }
+
// 3. Whether the new launched activity has already been in a split with a rule matched.
if (isNewActivityInSplitWithRuleMatched(activity)) {
return true;
@@ -2066,6 +2078,12 @@
if (!container.hasActivity(activityToken)
&& container.getTaskFragmentToken()
.equals(initialTaskFragmentToken)) {
+ if (ActivityClient.getInstance().isRequestedToLaunchInTaskFragment(
+ activityToken, initialTaskFragmentToken)) {
+ container.addPendingAppearedInRequestedTaskFragmentActivity(
+ activity);
+ }
+
// The onTaskFragmentInfoChanged callback containing this activity has
// not reached the client yet, so add the activity to the pending
// appeared activities.
@@ -2157,6 +2175,14 @@
// TODO(b/232042367): Consolidate the activity create handling so that we can handle
// cross-process the same as normal.
+ // Early return if the launching taskfragment is already been set.
+ if (options.getBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN) != null) {
+ synchronized (mLock) {
+ mCurrentIntent = intent;
+ }
+ return super.onStartActivity(who, intent, options);
+ }
+
final Activity launchingActivity;
if (who instanceof Activity) {
// We will check if the new activity should be split with the activity that launched
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index b38f824..6c553a8 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -86,6 +86,12 @@
@Nullable
private Intent mPendingAppearedIntent;
+ /**
+ * The activities that were explicitly requested to be launched in its current TaskFragment,
+ * but haven't been added to {@link #mInfo} yet.
+ */
+ final ArrayList<IBinder> mPendingAppearedInRequestedTaskFragmentActivities = new ArrayList<>();
+
/** Containers that are dependent on this one and should be completely destroyed on exit. */
private final List<TaskFragmentContainer> mContainersToFinishOnExit =
new ArrayList<>();
@@ -296,6 +302,8 @@
void removePendingAppearedActivity(@NonNull IBinder activityToken) {
mPendingAppearedActivities.remove(activityToken);
+ // Also remove the activity from the mPendingInRequestedTaskFragmentActivities.
+ mPendingAppearedInRequestedTaskFragmentActivities.remove(activityToken);
}
@GuardedBy("mController.mLock")
@@ -424,7 +432,7 @@
for (int i = mPendingAppearedActivities.size() - 1; i >= 0; --i) {
final IBinder activityToken = mPendingAppearedActivities.get(i);
if (infoActivities.contains(activityToken)) {
- mPendingAppearedActivities.remove(i);
+ removePendingAppearedActivity(activityToken);
}
}
}
@@ -720,6 +728,29 @@
mLastCompanionTaskFragment = fragmentToken;
}
+ /**
+ * Adds the pending appeared activity that has requested to be launched in this task fragment.
+ * @see android.app.ActivityClient#isRequestedToLaunchInTaskFragment
+ */
+ void addPendingAppearedInRequestedTaskFragmentActivity(Activity activity) {
+ final IBinder activityToken = activity.getActivityToken();
+ if (hasActivity(activityToken)) {
+ return;
+ }
+ mPendingAppearedInRequestedTaskFragmentActivities.add(activity.getActivityToken());
+ }
+
+ /**
+ * Checks if the given activity has requested to be launched in this task fragment.
+ * @see #addPendingAppearedInRequestedTaskFragmentActivity
+ */
+ boolean isActivityInRequestedTaskFragment(IBinder activityToken) {
+ if (mInfo != null && mInfo.getActivitiesRequestedInTaskFragment().contains(activityToken)) {
+ return true;
+ }
+ return mPendingAppearedInRequestedTaskFragmentActivities.contains(activityToken);
+ }
+
/** Gets the parent leaf Task id. */
int getTaskId() {
return mTaskContainer.getTaskId();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
index 459ec9f..a069ac7 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -177,6 +177,7 @@
1,
isVisible,
Collections.singletonList(activity.getActivityToken()),
+ new ArrayList<>(),
new Point(),
false /* isTaskClearedForReuse */,
false /* isTaskFragmentClearedForPip */,
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index bbb454d..dd087e8 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -124,7 +124,7 @@
private TaskFragmentInfo createMockInfo(TaskFragmentContainer container) {
return new TaskFragmentInfo(container.getTaskFragmentToken(),
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
- false /* isVisible */, new ArrayList<>(), new Point(),
+ false /* isVisible */, new ArrayList<>(), new ArrayList<>(), new Point(),
false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
false /* isClearedForReorderActivityToFront */, new Point());
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 61cd748..3d0e1c8 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -700,7 +700,7 @@
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
false /* isOnReparent */);
- assertFalse(result);
+ assertTrue(result);
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
any(), anyBoolean());
}
@@ -734,7 +734,7 @@
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
false /* isOnReparent */);
- assertFalse(result);
+ assertTrue(result);
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
any(), anyBoolean());
}
@@ -808,7 +808,7 @@
final Activity launchedActivity = createMockActivity();
primaryContainer.addPendingAppearedActivity(launchedActivity);
- assertFalse(mSplitController.resolveActivityToContainer(mTransaction, launchedActivity,
+ assertTrue(mSplitController.resolveActivityToContainer(mTransaction, launchedActivity,
false /* isOnReparent */));
}
@@ -944,7 +944,7 @@
boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
false /* isOnReparent */);
- assertFalse(result);
+ assertTrue(result);
assertEquals(primaryContainer, mSplitController.getContainerWithActivity(mActivity));
diff --git a/libs/WindowManager/Shell/res/color/split_divider_background.xml b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
similarity index 83%
rename from libs/WindowManager/Shell/res/color/split_divider_background.xml
rename to libs/WindowManager/Shell/res/color-night/taskbar_background.xml
index 0499808..9473cdd6 100644
--- a/libs/WindowManager/Shell/res/color/split_divider_background.xml
+++ b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2021 The Android Open Source Project
+ ~ Copyright (C) 2023 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.
@@ -14,6 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
+<!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/system_neutral1_500" android:lStar="15" />
</selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/color/taskbar_background.xml b/libs/WindowManager/Shell/res/color/taskbar_background.xml
index b3d26029..0e165fc 100644
--- a/libs/WindowManager/Shell/res/color/taskbar_background.xml
+++ b/libs/WindowManager/Shell/res/color/taskbar_background.xml
@@ -16,5 +16,5 @@
-->
<!-- Should be the same as in packages/apps/Launcher3/res/color-v31/taskbar_background.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="15" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="95" />
</selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
index 9167382..c6e634c 100644
--- a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
+++ b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
@@ -17,6 +17,6 @@
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
- <corners android:radius="20dp" />
+ <corners android:radius="@dimen/caption_menu_corner_radius" />
<stroke android:width="1dp" android:color="#b3b3b3"/>
</shape>
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
index f6e3f2e..f9aeb6a 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
@@ -21,7 +21,6 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/desktop_mode_decor_menu_background"
- android:elevation="@dimen/caption_menu_elevation"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="middle"
android:dividerPadding="18dip">
@@ -63,38 +62,46 @@
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="0.5" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/fullscreen_button"
android:contentDescription="@string/fullscreen_text"
- android:background="@drawable/caption_fullscreen_button"/>
+ android:src="@drawable/caption_fullscreen_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/split_screen_button"
android:contentDescription="@string/split_screen_text"
- android:background="@drawable/caption_split_screen_button"/>
+ android:src="@drawable/caption_split_screen_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/floating_button"
android:contentDescription="@string/float_button_text"
- android:background="@drawable/caption_floating_button"/>
+ android:src="@drawable/caption_floating_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/desktop_button"
android:contentDescription="@string/desktop_text"
- android:background="@drawable/caption_desktop_button"/>
+ android:src="@drawable/caption_desktop_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index e8edad1..413cfd7 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -16,9 +16,7 @@
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/system_neutral1_900">
+ style="@style/LetterboxDialog">
<!-- The background of the top-level layout acts as the background dim. -->
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
index ba9852c..5aff415 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
@@ -16,14 +16,10 @@
<com.android.wm.shell.compatui.RestartDialogLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/system_neutral1_900">
+ style="@style/LetterboxDialog">
<!-- The background of the top-level layout acts as the background dim. -->
- <!--TODO (b/266288912): Resolve overdraw warning -->
-
<!-- Vertical margin will be set dynamically since it depends on task bounds.
Setting the alpha of the dialog container to 0, since it shouldn't be visible until the
enter animation starts. -->
diff --git a/libs/WindowManager/Shell/res/values-night/colors.xml b/libs/WindowManager/Shell/res/values-night/colors.xml
index 83c4d93..5c6bb57 100644
--- a/libs/WindowManager/Shell/res/values-night/colors.xml
+++ b/libs/WindowManager/Shell/res/values-night/colors.xml
@@ -15,6 +15,7 @@
-->
<resources>
+ <color name="docked_divider_handle">#ffffff</color>
<!-- Bubbles -->
<color name="bubbles_icon_tint">@color/GM2_grey_200</color>
<!-- Splash screen-->
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 6e750a3..6fb70006 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -17,7 +17,8 @@
*/
-->
<resources>
- <color name="docked_divider_handle">#ffffff</color>
+ <color name="docked_divider_handle">#000000</color>
+ <color name="split_divider_background">@color/taskbar_background</color>
<drawable name="forced_resizable_background">#59000000</drawable>
<color name="minimize_dock_shadow_start">#60000000</color>
<color name="minimize_dock_shadow_end">#00000000</color>
@@ -41,6 +42,9 @@
<color name="letterbox_education_accent_primary">@android:color/system_accent1_100</color>
<color name="letterbox_education_text_secondary">@android:color/system_neutral2_200</color>
+ <!-- Letterbox Dialog -->
+ <color name="letterbox_dialog_background">@android:color/system_neutral1_900</color>
+
<!-- GM2 colors -->
<color name="GM2_grey_200">#E8EAED</color>
<color name="GM2_grey_700">#5F6368</color>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 336c156..680ad51 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -370,6 +370,10 @@
<dimen name="freeform_resize_corner">44dp</dimen>
- <dimen name="caption_menu_elevation">4dp</dimen>
+ <!-- The radius of the caption menu shadow. -->
+ <dimen name="caption_menu_shadow_radius">4dp</dimen>
+
+ <!-- The radius of the caption menu corners. -->
+ <dimen name="caption_menu_corner_radius">20dp</dimen>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index 0a0c49f..bc2e71d 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -38,11 +38,9 @@
</style>
<style name="CaptionWindowingButtonStyle">
- <item name="android:layout_width">32dp</item>
- <item name="android:layout_height">32dp</item>
+ <item name="android:layout_width">40dp</item>
+ <item name="android:layout_height">40dp</item>
<item name="android:padding">4dp</item>
- <item name="android:layout_marginTop">5dp</item>
- <item name="android:layout_marginBottom">5dp</item>
</style>
<style name="CaptionMenuButtonStyle" parent="@style/Widget.AppCompat.Button.Borderless">
@@ -80,6 +78,12 @@
<item name="android:textColor">@color/tv_pip_edu_text</item>
</style>
+ <style name="LetterboxDialog" parent="@android:style/Theme.Holo">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:background">@color/letterbox_dialog_background</item>
+ </style>
+
<style name="RestartDialogTitleText">
<item name="android:textSize">24sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index b3fff1d..0b87598 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -552,6 +552,9 @@
if (runner.isWaitingAnimation()) {
ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready.");
return;
+ } else if (runner.isAnimationCancelled()) {
+ invokeOrCancelBack();
+ return;
}
startPostCommitAnimation();
}
@@ -653,7 +656,19 @@
}
@Override
- public void onAnimationCancelled() { }
+ public void onAnimationCancelled() {
+ mShellExecutor.execute(() -> {
+ final BackAnimationRunner runner = mAnimationDefinition.get(
+ mBackNavigationInfo.getType());
+ if (runner == null) {
+ return;
+ }
+ runner.cancelAnimation();
+ if (!mBackGestureStarted) {
+ invokeOrCancelBack();
+ }
+ });
+ }
};
mBackAnimationAdapter = new BackAnimationAdapter(runner);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
index d70b8f5..82c523f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -41,6 +41,9 @@
// Whether we are waiting to receive onAnimationStart
private boolean mWaitingAnimation;
+ /** True when the back animation is cancelled */
+ private boolean mAnimationCancelled;
+
BackAnimationRunner(@NonNull IOnBackInvokedCallback callback,
@NonNull IRemoteAnimationRunner runner) {
mCallback = callback;
@@ -81,9 +84,19 @@
void startGesture() {
mWaitingAnimation = true;
+ mAnimationCancelled = false;
}
boolean isWaitingAnimation() {
return mWaitingAnimation;
}
+
+ void cancelAnimation() {
+ mWaitingAnimation = false;
+ mAnimationCancelled = true;
+ }
+
+ boolean isAnimationCancelled() {
+ return mAnimationCancelled;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 713dd39..69f0bad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -371,7 +371,14 @@
mViewHost.relayout(lp);
}
- void setInteractive(boolean interactive, String from) {
+ /**
+ * Set divider should interactive to user or not.
+ *
+ * @param interactive divider interactive.
+ * @param hideHandle divider handle hidden or not, only work when interactive is false.
+ * @param from caller from where.
+ */
+ void setInteractive(boolean interactive, boolean hideHandle, String from) {
if (interactive == mInteractive) return;
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
"Set divider bar %s from %s", interactive ? "interactive" : "non-interactive",
@@ -387,7 +394,7 @@
mMoving = false;
}
releaseTouching();
- mHandle.setVisibility(mInteractive ? View.VISIBLE : View.INVISIBLE);
+ mHandle.setVisibility(!mInteractive && hideHandle ? View.INVISIBLE : View.VISIBLE);
}
private boolean isLandscape() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 8a18271..b447a54 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -120,6 +120,7 @@
private int mOrientation;
private int mRotation;
private int mDensity;
+ private int mUiMode;
private final boolean mDimNonImeSide;
private ValueAnimator mDividerFlingAnimator;
@@ -295,10 +296,12 @@
final Rect rootBounds = configuration.windowConfiguration.getBounds();
final int orientation = configuration.orientation;
final int density = configuration.densityDpi;
+ final int uiMode = configuration.uiMode;
if (mOrientation == orientation
&& mRotation == rotation
&& mDensity == density
+ && mUiMode == uiMode
&& mRootBounds.equals(rootBounds)) {
return false;
}
@@ -310,6 +313,7 @@
mRootBounds.set(rootBounds);
mRotation = rotation;
mDensity = density;
+ mUiMode = uiMode;
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
updateDividerConfig(mContext);
initDividerPosition(mTempRect);
@@ -486,6 +490,17 @@
}
/**
+ * Set divider should interactive to user or not.
+ *
+ * @param interactive divider interactive.
+ * @param hideHandle divider handle hidden or not, only work when interactive is false.
+ * @param from caller from where.
+ */
+ public void setDividerInteractive(boolean interactive, boolean hideHandle, String from) {
+ mSplitWindowManager.setInteractive(interactive, hideHandle, from);
+ }
+
+ /**
* Sets new divide position and updates bounds correspondingly. Notifies listener if the new
* target indicates dismissing split.
*/
@@ -735,21 +750,28 @@
}
}
- /** Apply recorded task layout to the {@link WindowContainerTransaction}. */
- public void applyTaskChanges(WindowContainerTransaction wct,
+ /** Apply recorded task layout to the {@link WindowContainerTransaction}.
+ *
+ * @return true if stage bounds actually update.
+ */
+ public boolean applyTaskChanges(WindowContainerTransaction wct,
ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
+ boolean boundsChanged = false;
if (!mBounds1.equals(mWinBounds1) || !task1.token.equals(mWinToken1)) {
wct.setBounds(task1.token, mBounds1);
wct.setSmallestScreenWidthDp(task1.token, getSmallestWidthDp(mBounds1));
mWinBounds1.set(mBounds1);
mWinToken1 = task1.token;
+ boundsChanged = true;
}
if (!mBounds2.equals(mWinBounds2) || !task2.token.equals(mWinToken2)) {
wct.setBounds(task2.token, mBounds2);
wct.setSmallestScreenWidthDp(task2.token, getSmallestWidthDp(mBounds2));
mWinBounds2.set(mBounds2);
mWinToken2 = task2.token;
+ boundsChanged = true;
}
+ return boundsChanged;
}
private int getSmallestWidthDp(Rect bounds) {
@@ -1091,7 +1113,7 @@
// ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough
// because DividerView won't receive onImeVisibilityChanged callback after it being
// re-inflated.
- mSplitWindowManager.setInteractive(!mImeShown || !mHasImeFocus || isFloating,
+ setDividerInteractive(!mImeShown || !mHasImeFocus || isFloating, true,
"onImeStartPositioning");
return needOffset ? IME_ANIMATION_NO_ALPHA : 0;
@@ -1118,7 +1140,7 @@
// Restore the split layout when wm-shell is not controlling IME insets anymore.
if (!controlling && mImeShown) {
reset();
- mSplitWindowManager.setInteractive(true, "onImeControlTargetChanged");
+ setDividerInteractive(true, true, "onImeControlTargetChanged");
mSplitLayoutHandler.setLayoutOffsetTarget(0, 0, SplitLayout.this);
mSplitLayoutHandler.onLayoutPositionChanging(SplitLayout.this);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index eb3c1df..00361d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -168,9 +168,16 @@
}
}
- void setInteractive(boolean interactive, String from) {
+ /**
+ * Set divider should interactive to user or not.
+ *
+ * @param interactive divider interactive.
+ * @param hideHandle divider handle hidden or not, only work when interactive is false.
+ * @param from caller from where.
+ */
+ void setInteractive(boolean interactive, boolean hideHandle, String from) {
if (mDividerView == null) return;
- mDividerView.setInteractive(interactive, from);
+ mDividerView.setInteractive(interactive, hideHandle, from);
}
View getDividerView() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 3b2db51..76d9152 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -126,14 +126,12 @@
private final Lazy<Transitions> mTransitionsLazy;
private final DockStateReader mDockStateReader;
private final CompatUIConfiguration mCompatUIConfiguration;
-
- private CompatUICallback mCallback;
-
// Only show each hint once automatically in the process life.
private final CompatUIHintsState mCompatUIHintsState;
-
private final CompatUIShellCommandHandler mCompatUIShellCommandHandler;
+ private CompatUICallback mCallback;
+
// Indicates if the keyguard is currently showing, in which case compat UIs shouldn't
// be shown.
private boolean mKeyguardShowing;
@@ -372,19 +370,20 @@
RestartDialogWindowManager layout =
mTaskIdToRestartDialogWindowManagerMap.get(taskInfo.taskId);
if (layout != null) {
- // TODO(b/266262111) Handle theme change when taskListener changes
- if (layout.getTaskListener() != taskListener) {
- mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId);
- }
- layout.setRequestRestartDialog(
- mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
- // UI already exists, update the UI layout.
- if (!layout.updateCompatInfo(taskInfo, taskListener,
- showOnDisplay(layout.getDisplayId()))) {
- // The layout is no longer eligible to be shown, remove from active layouts.
+ if (layout.needsToBeRecreated(taskInfo, taskListener)) {
mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+ layout.release();
+ } else {
+ layout.setRequestRestartDialog(
+ mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
+ // UI already exists, update the UI layout.
+ if (!layout.updateCompatInfo(taskInfo, taskListener,
+ showOnDisplay(layout.getDisplayId()))) {
+ // The layout is no longer eligible to be shown, remove from active layouts.
+ mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+ }
+ return;
}
- return;
}
// Create a new UI layout.
final Context context = getOrCreateDisplayContext(taskInfo.displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index efd4594..b22c9c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -151,7 +151,6 @@
@Override
public void setConfiguration(Configuration configuration) {
super.setConfiguration(configuration);
- // TODO(b/266262111): Investigate loss of theme configuration when switching TaskListener
mContext = mContext.createConfigurationContext(configuration);
}
@@ -210,7 +209,8 @@
}
View layout = getLayout();
- if (layout == null || prevTaskListener != taskListener) {
+ if (layout == null || prevTaskListener != taskListener
+ || mTaskConfig.uiMode != prevTaskConfig.uiMode) {
// Layout wasn't created yet or TaskListener changed, recreate the layout for new
// surface parent.
release();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
index 10f25d0..2440838 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
@@ -155,6 +155,11 @@
return super.updateCompatInfo(taskInfo, taskListener, canShow);
}
+ boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
+ return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode
+ || !getTaskListener().equals(taskListener);
+ }
+
private void updateDialogMargins() {
if (mLayout == null) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index d1f4398..948bf2d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -196,7 +196,8 @@
DisplayController displayController,
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController) {
if (DesktopModeStatus.isAnyEnabled()) {
return new DesktopModeWindowDecorViewModel(
context,
@@ -206,7 +207,8 @@
displayController,
syncQueue,
desktopModeController,
- desktopTasksController);
+ desktopTasksController,
+ splitScreenController);
}
return new CaptionWindowDecorViewModel(
context,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index b59fe18..4cfaae6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -36,6 +36,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.content.ClipDescription;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
@@ -58,9 +59,9 @@
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.annotations.ExternalMainThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -70,7 +71,7 @@
* Handles the global drag and drop handling for the Shell.
*/
public class DragAndDropController implements DisplayController.OnDisplaysChangedListener,
- View.OnDragListener, ConfigurationChangeListener {
+ View.OnDragListener, ComponentCallbacks2 {
private static final String TAG = DragAndDropController.class.getSimpleName();
@@ -119,7 +120,6 @@
mMainExecutor.executeDelayed(() -> {
mDisplayController.addDisplayWindowListener(this);
}, 0);
- mShellController.addConfigurationChangeListener(this);
}
/**
@@ -180,6 +180,7 @@
try {
wm.addView(rootView, layoutParams);
addDisplayDropTarget(displayId, context, wm, rootView, dragLayout);
+ context.registerComponentCallbacks(this);
} catch (WindowManager.InvalidDisplayException e) {
Slog.w(TAG, "Unable to add view for display id: " + displayId);
}
@@ -209,6 +210,7 @@
if (pd == null) {
return;
}
+ pd.context.unregisterComponentCallbacks(this);
pd.wm.removeViewImmediate(pd.rootView);
mDisplayDropTargets.remove(displayId);
}
@@ -328,18 +330,29 @@
return mimeTypes;
}
- @Override
- public void onThemeChanged() {
- for (int i = 0; i < mDisplayDropTargets.size(); i++) {
- mDisplayDropTargets.get(i).dragLayout.onThemeChange();
- }
- }
-
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
@Override
public void onConfigurationChanged(Configuration newConfig) {
- for (int i = 0; i < mDisplayDropTargets.size(); i++) {
- mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
- }
+ mMainExecutor.execute(() -> {
+ for (int i = 0; i < mDisplayDropTargets.size(); i++) {
+ mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
+ }
+ });
+ }
+
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
+ @Override
+ public void onTrimMemory(int level) {
+ // Do nothing
+ }
+
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
+ @Override
+ public void onLowMemory() {
+ // Do nothing
}
private static class PerDisplay {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 44fd8ee..fe42822a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -18,6 +18,8 @@
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS;
+import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -72,6 +74,7 @@
private final SplitScreenController mSplitScreenController;
private final IconProvider mIconProvider;
private final StatusBarManager mStatusBarManager;
+ private final Configuration mLastConfiguration = new Configuration();
private DragAndDropPolicy.Target mCurrentTarget = null;
private DropZoneView mDropZoneView1;
@@ -92,6 +95,7 @@
mIconProvider = iconProvider;
mPolicy = new DragAndDropPolicy(context, splitScreenController);
mStatusBarManager = context.getSystemService(StatusBarManager.class);
+ mLastConfiguration.setTo(context.getResources().getConfiguration());
mDisplayMargin = context.getResources().getDimensionPixelSize(
R.dimen.drop_layout_display_margin);
@@ -132,11 +136,6 @@
return super.onApplyWindowInsets(insets);
}
- public void onThemeChange() {
- mDropZoneView1.onThemeChange();
- mDropZoneView2.onThemeChange();
- }
-
public void onConfigChanged(Configuration newConfig) {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
&& getOrientation() != HORIZONTAL) {
@@ -147,6 +146,15 @@
setOrientation(LinearLayout.VERTICAL);
updateContainerMargins(newConfig.orientation);
}
+
+ final int diff = newConfig.diff(mLastConfiguration);
+ final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0
+ || (diff & CONFIG_UI_MODE) != 0;
+ if (themeChanged) {
+ mDropZoneView1.onThemeChange();
+ mDropZoneView2.onThemeChange();
+ }
+ mLastConfiguration.setTo(newConfig);
}
private void updateContainerMarginsForSingleTask() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index fee9140..e6f47d4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -32,6 +32,7 @@
import android.hardware.input.InputManager;
import android.os.Looper;
import android.provider.DeviceConfig;
+import android.util.Log;
import android.view.BatchedInputEventReceiver;
import android.view.Choreographer;
import android.view.InputChannel;
@@ -243,6 +244,7 @@
@VisibleForTesting
void onInputEvent(InputEvent ev) {
+ Log.d(TAG, "onInputEvent: " + ev);
if (!mEnableDragCornerResize && !mEnablePinchResize) {
// No need to handle anything if neither form of resizing is enabled.
return;
@@ -256,6 +258,17 @@
if (ev instanceof MotionEvent) {
MotionEvent mv = (MotionEvent) ev;
int action = mv.getActionMasked();
+
+ // TODO: remove logging once b/269505548 is resolved
+ if (action == MotionEvent.ACTION_MOVE && mFirstIndex != -1 && mSecondIndex != -1) {
+ float x0 = mv.getRawX(mFirstIndex);
+ float y0 = mv.getRawY(mFirstIndex);
+ float x1 = mv.getRawX(mSecondIndex);
+ float y1 = mv.getRawY(mSecondIndex);
+ Log.d(TAG, "at onInputEvent (" + x0 + ", " + y0 + ")");
+ Log.d(TAG, "at onInputEvent (" + x1 + ", " + y1 + ")");
+ }
+
final Rect pipBounds = mPipBoundsState.getBounds();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
if (!pipBounds.contains((int) mv.getRawX(), (int) mv.getRawY())
@@ -393,6 +406,7 @@
@VisibleForTesting
void onPinchResize(MotionEvent ev) {
+ Log.d(TAG, "onPinchResize: " + ev);
int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
@@ -436,6 +450,10 @@
mLastPoint.set(x0, y0);
mLastSecondPoint.set(x1, y1);
+ // TODO: remove logging once b/269505548 is resolved
+ Log.d(TAG, "at onPinchResize (" + x0 + ", " + y0 + ")");
+ Log.d(TAG, "at onPinchResize (" + x1 + ", " + y1 + ")");
+
// Capture inputs
if (!mThresholdCrossed
&& (distanceBetween(mDownSecondPoint, mLastSecondPoint) > mTouchSlop
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
index 8895fca..73123b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
@@ -25,16 +25,14 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Insets;
-import android.graphics.Matrix;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
-import android.view.SyncRtSurfaceTransactionApplier;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
+import android.window.SurfaceSyncGroup;
import androidx.annotation.Nullable;
@@ -71,12 +69,6 @@
// exiting the move menu instead of showing the regular button menu.
private boolean mCloseAfterExitMoveMenu;
- private SyncRtSurfaceTransactionApplier mApplier;
- private SyncRtSurfaceTransactionApplier mBackgroundApplier;
- RectF mTmpSourceRectF = new RectF();
- RectF mTmpDestinationRectF = new RectF();
- Matrix mMoveTransform = new Matrix();
-
public TvPipMenuController(Context context, TvPipBoundsState tvPipBoundsState,
SystemWindows systemWindows, Handler mainHandler) {
mContext = context;
@@ -324,44 +316,36 @@
*/
@Override
public void resizePipMenu(@Nullable SurfaceControl pipLeash,
- @Nullable SurfaceControl.Transaction t,
- Rect destinationBounds) {
+ @Nullable SurfaceControl.Transaction pipTx,
+ Rect pipBounds) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: resizePipMenu: %s", TAG, destinationBounds.toShortString());
- if (destinationBounds.isEmpty()) {
+ "%s: resizePipMenu: %s", TAG, pipBounds.toShortString());
+ if (pipBounds.isEmpty()) {
return;
}
- if (!maybeCreateSyncApplier()) {
+ if (!isMenuReadyToMove()) {
return;
}
- final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds);
final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
- .withWindowCrop(menuBounds)
- .build();
-
final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams backParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface)
- .withWindowCrop(menuBounds)
- .build();
-
- // TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
- // animations of the pip surface with the content of the front and back menu surfaces
- mBackgroundApplier.scheduleApply(backParams);
- if (pipLeash != null && t != null) {
- final SyncRtSurfaceTransactionApplier.SurfaceParams
- pipParams = new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
- .withMergeTransaction(t)
- .build();
- mApplier.scheduleApply(frontParams, pipParams);
- } else {
- mApplier.scheduleApply(frontParams);
+ final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
+ if (pipTx == null) {
+ pipTx = new SurfaceControl.Transaction();
}
+ pipTx.setWindowCrop(frontSurface, menuBounds.width(), menuBounds.height());
+ pipTx.setWindowCrop(backSurface, menuBounds.width(), menuBounds.height());
+
+ // Synchronize drawing the content in the front and back surfaces together with the pip
+ // transaction and the window crop for the front and back surfaces
+ final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
+ syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
+ syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
+ updateMenuBounds(pipBounds);
+ syncGroup.addTransaction(pipTx);
+ syncGroup.markSyncReady();
}
private SurfaceControl getSurfaceControl(View v) {
@@ -369,102 +353,66 @@
}
@Override
- public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction transaction,
- Rect pipDestBounds) {
+ public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction pipTx,
+ Rect pipBounds) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: movePipMenu: %s", TAG, pipDestBounds.toShortString());
+ "%s: movePipMenu: %s", TAG, pipBounds.toShortString());
- if (pipDestBounds.isEmpty()) {
- if (transaction == null) {
+ if (pipBounds.isEmpty()) {
+ if (pipTx == null) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: no transaction given", TAG);
}
return;
}
- if (!maybeCreateSyncApplier()) {
+ if (!isMenuReadyToMove()) {
return;
}
- final Rect menuDestBounds = calculateMenuSurfaceBounds(pipDestBounds);
- final Rect tmpSourceBounds = new Rect();
- // If there is no pip leash supplied, that means the PiP leash is already finalized
- // resizing and the PiP menu is also resized. We then want to do a scale from the current
- // new menu bounds.
- if (pipLeash != null && transaction != null) {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: tmpSourceBounds based on mPipMenuView.getBoundsOnScreen()", TAG);
- mPipMenuView.getBoundsOnScreen(tmpSourceBounds);
- } else {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: tmpSourceBounds based on menu width and height", TAG);
- tmpSourceBounds.set(0, 0, menuDestBounds.width(), menuDestBounds.height());
- }
-
- mTmpSourceRectF.set(tmpSourceBounds);
- mTmpDestinationRectF.set(menuDestBounds);
- mMoveTransform.setTranslate(mTmpDestinationRectF.left, mTmpDestinationRectF.top);
-
final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
- .withMatrix(mMoveTransform)
- .build();
-
final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams backParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface)
- .withMatrix(mMoveTransform)
- .build();
-
- // TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
- // animations of the pip surface with the content of the front and back menu surfaces
- mBackgroundApplier.scheduleApply(backParams);
- if (pipLeash != null && transaction != null) {
- final SyncRtSurfaceTransactionApplier.SurfaceParams pipParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
- .withMergeTransaction(transaction)
- .build();
- mApplier.scheduleApply(frontParams, pipParams);
- } else {
- mApplier.scheduleApply(frontParams);
+ final Rect menuDestBounds = calculateMenuSurfaceBounds(pipBounds);
+ if (pipTx == null) {
+ pipTx = new SurfaceControl.Transaction();
}
+ pipTx.setPosition(frontSurface, menuDestBounds.left, menuDestBounds.top);
+ pipTx.setPosition(backSurface, menuDestBounds.left, menuDestBounds.top);
- updateMenuBounds(pipDestBounds);
+ // Synchronize drawing the content in the front and back surfaces together with the pip
+ // transaction and the position change for the front and back surfaces
+ final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
+ syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
+ syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
+ updateMenuBounds(pipBounds);
+ syncGroup.addTransaction(pipTx);
+ syncGroup.markSyncReady();
}
- private boolean maybeCreateSyncApplier() {
- if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) {
+ private boolean isMenuReadyToMove() {
+ final boolean ready = mPipMenuView != null && mPipMenuView.getViewRootImpl() != null
+ && mPipBackgroundView != null && mPipBackgroundView.getViewRootImpl() != null;
+ if (!ready) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Not going to move PiP, either menu or its parent is not created.", TAG);
- return false;
}
-
- if (mApplier == null) {
- mApplier = new SyncRtSurfaceTransactionApplier(mPipMenuView);
- }
- if (mBackgroundApplier == null) {
- mBackgroundApplier = new SyncRtSurfaceTransactionApplier(mPipBackgroundView);
- }
- return true;
+ return ready;
}
private void detachPipMenu() {
if (mPipMenuView != null) {
- mApplier = null;
mSystemWindows.removeView(mPipMenuView);
mPipMenuView = null;
}
if (mPipBackgroundView != null) {
- mBackgroundApplier = null;
mSystemWindows.removeView(mPipBackgroundView);
mPipBackgroundView = null;
}
}
@Override
- public void updateMenuBounds(Rect destinationBounds) {
- final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds);
+ public void updateMenuBounds(Rect pipBounds) {
+ final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: updateMenuBounds: %s", TAG, menuBounds.toShortString());
mSystemWindows.updateViewLayout(mPipBackgroundView,
@@ -473,9 +421,8 @@
mSystemWindows.updateViewLayout(mPipMenuView,
getPipMenuLayoutParams(mContext, MENU_WINDOW_TITLE, menuBounds.width(),
menuBounds.height()));
-
if (mPipMenuView != null) {
- mPipMenuView.updateBounds(destinationBounds);
+ mPipMenuView.updateBounds(pipBounds);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index c7ad4fd..94b9e90 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -422,6 +422,11 @@
mStageCoordinator.goToFullscreenFromSplit();
}
+ /** Move the specified task to fullscreen, regardless of focus state. */
+ public void moveTaskToFullscreen(int taskId) {
+ mStageCoordinator.moveTaskToFullscreen(taskId);
+ }
+
public boolean isLaunchToSplit(TaskInfo taskInfo) {
return mStageCoordinator.isLaunchToSplit(taskInfo);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index c96323a..e1c0895 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -340,6 +340,12 @@
IBinder startResizeTransition(WindowContainerTransaction wct,
Transitions.TransitionHandler handler,
@Nullable TransitionFinishedCallback finishCallback) {
+ if (mPendingResize != null) {
+ mPendingResize.cancel(null);
+ mAnimations.clear();
+ onFinish(null /* wct */, null /* wctCB */);
+ }
+
IBinder transition = mTransitions.startTransition(TRANSIT_CHANGE, wct, handler);
setResizeTransition(transition, finishCallback);
return transition;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 8b24d86..2252587 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -20,7 +20,6 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED;
import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -661,6 +660,7 @@
@Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ prepareEvictChildTasksIfSplitActive(wct);
setSideStagePosition(splitPosition, wct);
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
@@ -675,6 +675,7 @@
@SplitPosition int splitPosition, float splitRatio,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ prepareEvictChildTasksIfSplitActive(wct);
setSideStagePosition(splitPosition, wct);
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
@@ -688,6 +689,7 @@
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ prepareEvictChildTasksIfSplitActive(wct);
setSideStagePosition(splitPosition, wct);
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
@@ -706,10 +708,7 @@
private void startWithTask(WindowContainerTransaction wct, int mainTaskId,
@Nullable Bundle mainOptions, float splitRatio,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
- if (mMainStage.isActive()) {
- mMainStage.evictAllChildren(wct);
- mSideStage.evictAllChildren(wct);
- } else {
+ if (!mMainStage.isActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
// while task 1 is on the side stage.
mMainStage.activate(wct, false /* reparent */);
@@ -937,7 +936,7 @@
new IRemoteAnimationFinishedCallback.Stub() {
@Override
public void onAnimationFinished() throws RemoteException {
- onRemoteAnimationFinishedOrCancelled(false /* cancel */, evictWct);
+ onRemoteAnimationFinishedOrCancelled(evictWct);
finishedCallback.onAnimationFinished();
}
};
@@ -953,7 +952,7 @@
@Override
public void onAnimationCancelled(boolean isKeyguardOccluded) {
- onRemoteAnimationFinishedOrCancelled(true /* cancel */, evictWct);
+ onRemoteAnimationFinishedOrCancelled(evictWct);
try {
adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
} catch (RemoteException e) {
@@ -974,15 +973,14 @@
}
}
- private void onRemoteAnimationFinishedOrCancelled(boolean cancel,
- WindowContainerTransaction evictWct) {
+ private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) {
mIsSplitEntering = false;
mShouldUpdateRecents = true;
mSplitRequest = null;
// If any stage has no child after animation finished, it means that split will display
// nothing, such status will happen if task and intent is same app but not support
// multi-instance, we should exit split and expand that app as full screen.
- if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
+ if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
mMainExecutor.execute(() ->
exitSplitScreen(mMainStage.getChildCount() == 0
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
@@ -1021,6 +1019,13 @@
mSideStage.evictInvisibleChildren(wct);
}
+ void prepareEvictChildTasksIfSplitActive(WindowContainerTransaction wct) {
+ if (mMainStage.isActive()) {
+ mMainStage.evictAllChildren(wct);
+ mSideStage.evictAllChildren(wct);
+ }
+ }
+
Bundle resolveStartStage(@StageType int stage, @SplitPosition int position,
@Nullable Bundle options, @Nullable WindowContainerTransaction wct) {
switch (stage) {
@@ -1237,8 +1242,8 @@
// Notify recents if we are exiting in a way that breaks the pair, and disable further
// updates to splits in the recents until we enter split again
if (shouldBreakPairedTaskInRecents(exitReason) && mShouldUpdateRecents) {
- recentTasks.removeSplitPair(mMainStage.getLastVisibleTaskId());
- recentTasks.removeSplitPair(mSideStage.getLastVisibleTaskId());
+ recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId());
+ recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId());
}
});
mShouldUpdateRecents = false;
@@ -1925,10 +1930,14 @@
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
- updateWindowBounds(layout, wct);
+ boolean sizeChanged = updateWindowBounds(layout, wct);
+ if (!sizeChanged) return;
+
sendOnBoundsChanged();
if (ENABLE_SHELL_TRANSITIONS) {
- mSplitTransitions.startResizeTransition(wct, this, null /* callback */);
+ mSplitLayout.setDividerInteractive(false, false, "onSplitResizeStart");
+ mSplitTransitions.startResizeTransition(wct, this, (finishWct, t) ->
+ mSplitLayout.setDividerInteractive(true, false, "onSplitResizeFinish"));
} else {
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
@@ -1947,13 +1956,16 @@
/**
* Populates `wct` with operations that match the split windows to the current layout.
* To match relevant surfaces, make sure to call updateSurfaceBounds after `wct` is applied
+ *
+ * @return true if stage bounds actually .
*/
- private void updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
+ private boolean updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
final StageTaskListener topLeftStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
final StageTaskListener bottomRightStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
- layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
+ return layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo,
+ bottomRightStage.mRootTaskInfo);
}
void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t,
@@ -2154,19 +2166,11 @@
}
} else if (isOpening && inFullscreen) {
final int activityType = triggerTask.getActivityType();
- if (activityType == ACTIVITY_TYPE_ASSISTANT) {
- // We don't want assistant panel to dismiss split screen, so do nothing.
- } else if (activityType == ACTIVITY_TYPE_HOME
+ if (activityType == ACTIVITY_TYPE_HOME
|| activityType == ACTIVITY_TYPE_RECENTS) {
// Enter overview panel, so start recent transition.
mSplitTransitions.setRecentTransition(transition, request.getRemoteTransition(),
mRecentTransitionFinishedCallback);
- } else if (mSplitTransitions.mPendingRecent == null) {
- // If split-task is not controlled by recents animation
- // and occluded by the other fullscreen task, dismiss both.
- prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
- mSplitTransitions.setDismissTransition(
- transition, STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN);
}
}
} else {
@@ -2400,6 +2404,20 @@
mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
}
+ /** Move the specified task to fullscreen, regardless of focus state. */
+ public void moveTaskToFullscreen(int taskId) {
+ boolean leftOrTop;
+ if (mMainStage.containsTask(taskId)) {
+ leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+ } else if (mSideStage.containsTask(taskId)) {
+ leftOrTop = (mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT);
+ } else {
+ return;
+ }
+ mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
+
+ }
+
boolean isLaunchToSplit(TaskInfo taskInfo) {
return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 0359761..a841b7f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -92,7 +92,6 @@
protected SurfaceControl mDimLayer;
protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
- private int mLastVisibleTaskId = INVALID_TASK_ID;
// TODO(b/204308910): Extracts SplitDecorManager related code to common package.
private SplitDecorManager mSplitDecorManager;
@@ -124,13 +123,6 @@
}
/**
- * Returns the last visible task's id.
- */
- int getLastVisibleTaskId() {
- return mLastVisibleTaskId;
- }
-
- /**
* Returns the top visible child task's id.
*/
int getTopVisibleChildTaskId() {
@@ -229,9 +221,6 @@
return;
}
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
- if (taskInfo.isVisible && taskInfo.taskId != mLastVisibleTaskId) {
- mLastVisibleTaskId = taskInfo.taskId;
- }
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
taskInfo.isVisible);
if (!ENABLE_SHELL_TRANSITIONS) {
@@ -264,9 +253,6 @@
} else if (mChildrenTaskInfo.contains(taskId)) {
mChildrenTaskInfo.remove(taskId);
mChildrenLeashes.remove(taskId);
- if (taskId == mLastVisibleTaskId) {
- mLastVisibleTaskId = INVALID_TASK_ID;
- }
mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
if (ENABLE_SHELL_TRANSITIONS) {
// Status is managed/synchronized by the transition lifecycle.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
index ac52235..2e2f569 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
@@ -21,6 +21,7 @@
import android.os.Build;
import android.os.SystemClock;
import android.util.Pair;
+import android.view.SurfaceControl;
import androidx.annotation.VisibleForTesting;
@@ -75,6 +76,7 @@
@VisibleForTesting
public void init() {
ProtoLog.v(WM_SHELL_INIT, "Initializing Shell Components: %d", mInitCallbacks.size());
+ SurfaceControl.setDebugUsageAfterRelease(true);
// Init in order of registration
for (int i = 0; i < mInitCallbacks.size(); i++) {
final Pair<String, Runnable> info = mInitCallbacks.get(i);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
index 145f759..8c6e1e7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -16,18 +16,40 @@
package com.android.wm.shell.util;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.view.RemoteAnimationTarget.MODE_CHANGING;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
+import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+
+import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.WindowConfiguration;
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.SparseBooleanArray;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
+import java.util.function.Predicate;
+
/** Various utility functions for transitions. */
public class TransitionUtil {
@@ -54,4 +76,189 @@
return false;
}
+ /** Returns `true` if `change` is a wallpaper. */
+ public static boolean isWallpaper(TransitionInfo.Change change) {
+ return (change.getTaskInfo() == null)
+ && change.hasFlags(FLAG_IS_WALLPAPER)
+ && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+ }
+
+ /** Returns `true` if `change` is not an app window or wallpaper. */
+ public static boolean isNonApp(TransitionInfo.Change change) {
+ return (change.getTaskInfo() == null)
+ && !change.hasFlags(FLAG_IS_WALLPAPER)
+ && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+ }
+
+ /**
+ * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
+ * MUST call `test` in the same order that the changes appear in the TransitionInfo.
+ */
+ public static class LeafTaskFilter implements Predicate<TransitionInfo.Change> {
+ private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
+
+ @Override
+ public boolean test(TransitionInfo.Change change) {
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ // Children always come before parent since changes are in top-to-bottom z-order.
+ if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
+ // has children, so not a leaf. Skip.
+ return false;
+ }
+ if (taskInfo.hasParentTask()) {
+ mChildTaskTargets.put(taskInfo.parentTaskId, true);
+ }
+ return true;
+ }
+ }
+
+
+ private static int newModeToLegacyMode(int newMode) {
+ switch (newMode) {
+ case WindowManager.TRANSIT_OPEN:
+ case WindowManager.TRANSIT_TO_FRONT:
+ return MODE_OPENING;
+ case WindowManager.TRANSIT_CLOSE:
+ case WindowManager.TRANSIT_TO_BACK:
+ return MODE_CLOSING;
+ default:
+ return MODE_CHANGING;
+ }
+ }
+
+ /**
+ * Very similar to Transitions#setupAnimHierarchy but specialized for leashes.
+ */
+ @SuppressLint("NewApi")
+ private static void setupLeash(@NonNull SurfaceControl leash,
+ @NonNull TransitionInfo.Change change, int layer,
+ @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
+ final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
+ // Put animating stuff above this line and put static stuff below it.
+ int zSplitLine = info.getChanges().size();
+ // changes should be ordered top-to-bottom in z
+ final int mode = change.getMode();
+
+ t.reparent(leash, info.getRootLeash());
+ final Rect absBounds =
+ (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
+ t.setPosition(leash, absBounds.left - info.getRootOffset().x,
+ absBounds.top - info.getRootOffset().y);
+
+ // Put all the OPEN/SHOW on top
+ if (TransitionUtil.isOpeningType(mode)) {
+ if (isOpening) {
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
+ // if transferred, it should be left visible.
+ t.setAlpha(leash, 0.f);
+ }
+ } else {
+ // put on bottom and leave it visible
+ t.setLayer(leash, zSplitLine - layer);
+ }
+ } else if (TransitionUtil.isClosingType(mode)) {
+ if (isOpening) {
+ // put on bottom and leave visible
+ t.setLayer(leash, zSplitLine - layer);
+ } else {
+ // put on top
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ }
+ } else { // CHANGE
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ }
+ }
+
+ @SuppressLint("NewApi")
+ private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
+ int order, SurfaceControl.Transaction t) {
+ // TODO: once we can properly sync transactions across process, then get rid of this leash.
+ if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
+ // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
+ // making leashes means we have to handle them specially.
+ return change.getLeash();
+ }
+ SurfaceControl leashSurface = new SurfaceControl.Builder()
+ .setName(change.getLeash().toString() + "_transition-leash")
+ .setContainerLayer()
+ // Initial the surface visible to respect the visibility of the original surface.
+ .setHidden(false)
+ .setParent(info.getRootLeash())
+ .build();
+ // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
+ setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
+ t.reparent(change.getLeash(), leashSurface);
+ t.setAlpha(change.getLeash(), 1.0f);
+ t.show(change.getLeash());
+ t.setPosition(change.getLeash(), 0, 0);
+ t.setLayer(change.getLeash(), 0);
+ return leashSurface;
+ }
+
+ /**
+ * Creates a new RemoteAnimationTarget from the provided change info
+ */
+ public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+ TransitionInfo info, SurfaceControl.Transaction t,
+ @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
+ final SurfaceControl leash = createLeash(info, change, order, t);
+ if (leashMap != null) {
+ leashMap.put(change.getLeash(), leash);
+ }
+ return newTarget(change, order, leash);
+ }
+
+ /**
+ * Creates a new RemoteAnimationTarget from the provided change and leash
+ */
+ public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+ SurfaceControl leash) {
+ int taskId;
+ boolean isNotInRecents;
+ ActivityManager.RunningTaskInfo taskInfo;
+ WindowConfiguration windowConfiguration;
+
+ taskInfo = change.getTaskInfo();
+ if (taskInfo != null) {
+ taskId = taskInfo.taskId;
+ isNotInRecents = !taskInfo.isRunning;
+ windowConfiguration = taskInfo.configuration.windowConfiguration;
+ } else {
+ taskId = INVALID_TASK_ID;
+ isNotInRecents = true;
+ windowConfiguration = new WindowConfiguration();
+ }
+
+ Rect localBounds = new Rect(change.getEndAbsBounds());
+ localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
+
+ RemoteAnimationTarget target = new RemoteAnimationTarget(
+ taskId,
+ newModeToLegacyMode(change.getMode()),
+ // TODO: once we can properly sync transactions across process,
+ // then get rid of this leash.
+ leash,
+ (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
+ null,
+ // TODO(shell-transitions): we need to send content insets? evaluate how its used.
+ new Rect(0, 0, 0, 0),
+ order,
+ null,
+ localBounds,
+ new Rect(change.getEndAbsBounds()),
+ windowConfiguration,
+ isNotInRecents,
+ null,
+ new Rect(change.getStartAbsBounds()),
+ taskInfo,
+ change.getAllowEnterPip(),
+ (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
+ ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
+ );
+ target.setWillShowImeOnTarget(
+ (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
+ target.setRotationChange(change.getEndRotation() - change.getStartRotation());
+ return target;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 766c4cd..2aa6d12 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -20,10 +20,14 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.content.Context;
+import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
@@ -37,7 +41,6 @@
import android.view.SurfaceControl;
import android.view.View;
import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
import androidx.annotation.Nullable;
@@ -50,6 +53,7 @@
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Optional;
@@ -80,6 +84,8 @@
private final InputMonitorFactory mInputMonitorFactory;
private TaskOperations mTaskOperations;
+ private Optional<SplitScreenController> mSplitScreenController;
+
public DesktopModeWindowDecorViewModel(
Context context,
Handler mainHandler,
@@ -88,7 +94,8 @@
DisplayController displayController,
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController) {
this(
context,
mainHandler,
@@ -98,6 +105,7 @@
syncQueue,
desktopModeController,
desktopTasksController,
+ splitScreenController,
new DesktopModeWindowDecoration.Factory(),
new InputMonitorFactory());
}
@@ -112,6 +120,7 @@
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController,
DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
InputMonitorFactory inputMonitorFactory) {
mContext = context;
@@ -120,6 +129,7 @@
mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
mTaskOrganizer = taskOrganizer;
mDisplayController = displayController;
+ mSplitScreenController = splitScreenController;
mSyncQueue = syncQueue;
mDesktopModeController = desktopModeController;
mDesktopTasksController = desktopTasksController;
@@ -230,6 +240,15 @@
final int id = v.getId();
if (id == R.id.close_window || id == R.id.close_button) {
mTaskOperations.closeTask(mTaskToken);
+ if (mSplitScreenController.isPresent()
+ && mSplitScreenController.get().isSplitScreenVisible()) {
+ int remainingTaskPosition = mTaskId == mSplitScreenController.get()
+ .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
+ ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
+ ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get()
+ .getTaskInfo(remainingTaskPosition);
+ mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId);
+ }
} else if (id == R.id.back_button) {
mTaskOperations.injectBackKey();
} else if (id == R.id.caption_handle) {
@@ -261,9 +280,6 @@
if (taskInfo.isFocused) {
return mDragDetector.isDragEvent();
}
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.reorder(mTaskToken, true /* onTop */);
- mSyncQueue.queue(wct);
return false;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
@@ -401,14 +417,14 @@
* @param ev the {@link MotionEvent} received by {@link EventReceiver}
*/
private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
+ final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
if (DesktopModeStatus.isProto2Enabled()) {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null
- || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- handleCaptionThroughStatusBar(ev);
+ if (relevantDecor == null
+ || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+ handleCaptionThroughStatusBar(ev, relevantDecor);
}
}
- handleEventOutsideFocusedCaption(ev);
+ handleEventOutsideFocusedCaption(ev, relevantDecor);
// Prevent status bar from reacting to a caption drag.
if (DesktopModeStatus.isProto2Enabled()) {
if (mTransitionDragActive) {
@@ -422,16 +438,16 @@
}
// If an UP/CANCEL action is received outside of caption bounds, turn off handle menu
- private void handleEventOutsideFocusedCaption(MotionEvent ev) {
+ private void handleEventOutsideFocusedCaption(MotionEvent ev,
+ DesktopModeWindowDecoration relevantDecor) {
final int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null) {
+ if (relevantDecor == null) {
return;
}
if (!mTransitionDragActive) {
- focusedDecor.closeHandleMenuIfNeeded(ev);
+ relevantDecor.closeHandleMenuIfNeeded(ev);
}
}
}
@@ -441,39 +457,38 @@
* Perform caption actions if not able to through normal means.
* Turn on desktop mode if handle is dragged below status bar.
*/
- private void handleCaptionThroughStatusBar(MotionEvent ev) {
+ private void handleCaptionThroughStatusBar(MotionEvent ev,
+ DesktopModeWindowDecoration relevantDecor) {
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
// Begin drag through status bar if applicable.
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor != null) {
+ if (relevantDecor != null) {
boolean dragFromStatusBarAllowed = false;
if (DesktopModeStatus.isProto2Enabled()) {
// In proto2 any full screen task can be dragged to freeform
- dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode()
+ dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode()
== WINDOWING_MODE_FULLSCREEN;
}
- if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) {
+ if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) {
mTransitionDragActive = true;
}
}
break;
}
case MotionEvent.ACTION_UP: {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null) {
+ if (relevantDecor == null) {
mTransitionDragActive = false;
return;
}
if (mTransitionDragActive) {
mTransitionDragActive = false;
final int statusBarHeight = mDisplayController
- .getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top;
+ .getDisplayLayout(relevantDecor.mTaskInfo.displayId).stableInsets().top;
if (ev.getY() > statusBarHeight) {
if (DesktopModeStatus.isProto2Enabled()) {
mDesktopTasksController.ifPresent(
- c -> c.moveToDesktop(focusedDecor.mTaskInfo));
+ c -> c.moveToDesktop(relevantDecor.mTaskInfo));
} else if (DesktopModeStatus.isProto1Enabled()) {
mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
}
@@ -481,7 +496,7 @@
return;
}
}
- focusedDecor.checkClickEvent(ev);
+ relevantDecor.checkClickEvent(ev);
break;
}
case MotionEvent.ACTION_CANCEL: {
@@ -491,6 +506,38 @@
}
@Nullable
+ private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
+ if (mSplitScreenController.isPresent()
+ && mSplitScreenController.get().isSplitScreenVisible()) {
+ // We can't look at focused task here as only one task will have focus.
+ return getSplitScreenDecor(ev);
+ } else {
+ return getFocusedDecor();
+ }
+ }
+
+ @Nullable
+ private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) {
+ ActivityManager.RunningTaskInfo topOrLeftTask =
+ mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
+ ActivityManager.RunningTaskInfo bottomOrRightTask =
+ mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
+ if (topOrLeftTask != null && topOrLeftTask.getConfiguration()
+ .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+ return mWindowDecorByTaskId.get(topOrLeftTask.taskId);
+ } else if (bottomOrRightTask != null && bottomOrRightTask.getConfiguration()
+ .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+ Rect bottomOrRightBounds = bottomOrRightTask.getConfiguration().windowConfiguration
+ .getBounds();
+ ev.offsetLocation(-bottomOrRightBounds.left, -bottomOrRightBounds.top);
+ return mWindowDecorByTaskId.get(bottomOrRightTask.taskId);
+ } else {
+ return null;
+ }
+
+ }
+
+ @Nullable
private DesktopModeWindowDecoration getFocusedDecor() {
final int size = mWindowDecorByTaskId.size();
DesktopModeWindowDecoration focusedDecor = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 0779f1d..72da108 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -74,6 +74,8 @@
private boolean mDesktopActive;
private AdditionalWindow mHandleMenu;
private final int mHandleMenuWidthId = R.dimen.freeform_decor_caption_menu_width;
+ private final int mHandleMenuShadowRadiusId = R.dimen.caption_menu_shadow_radius;
+ private final int mHandleMenuCornerRadiusId = R.dimen.caption_menu_corner_radius;
private PointF mHandleMenuPosition = new PointF();
DesktopModeWindowDecoration(
@@ -353,19 +355,16 @@
.windowConfiguration.getBounds().width();
final int menuWidth = loadDimensionPixelSize(resources, mHandleMenuWidthId);
final int menuHeight = loadDimensionPixelSize(resources, mCaptionMenuHeightId);
-
- // Elevation gives the appearance of a changed x/y coordinate; this is to fix that
- int elevationOffset = 2 * loadDimensionPixelSize(resources,
- R.dimen.caption_menu_elevation);
+ final int shadowRadius = loadDimensionPixelSize(resources, mHandleMenuShadowRadiusId);
+ final int cornerRadius = loadDimensionPixelSize(resources, mHandleMenuCornerRadiusId);
final int x = mRelayoutParams.mCaptionX + (captionWidth / 2) - (menuWidth / 2)
- - mResult.mDecorContainerOffsetX - elevationOffset;
- final int y =
- mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY - elevationOffset;
+ - mResult.mDecorContainerOffsetX;
+ final int y = mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY;
mHandleMenuPosition.set(x, y);
String namePrefix = "Caption Menu";
mHandleMenu = addWindow(R.layout.desktop_mode_decor_handle_menu, namePrefix, t, x, y,
- menuWidth, menuHeight, 2 * elevationOffset);
+ menuWidth, menuHeight, shadowRadius, cornerRadius);
mSyncQueue.runInSync(transaction -> {
transaction.merge(t);
t.close();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 91b0aa1..7a7ac47 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -391,11 +391,12 @@
* @param yPos y position of new window
* @param width width of new window
* @param height height of new window
- * @param cropPadding padding to add to window crop to ensure shadows display properly
- * @return
+ * @param shadowRadius radius of the shadow of the new window
+ * @param cornerRadius radius of the corners of the new window
+ * @return the {@link AdditionalWindow} that was added.
*/
AdditionalWindow addWindow(int layoutId, String namePrefix, SurfaceControl.Transaction t,
- int xPos, int yPos, int width, int height, int cropPadding) {
+ int xPos, int yPos, int width, int height, int shadowRadius, int cornerRadius) {
final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
SurfaceControl windowSurfaceControl = builder
.setName(namePrefix + " of Task=" + mTaskInfo.taskId)
@@ -404,9 +405,10 @@
.build();
View v = LayoutInflater.from(mDecorWindowContext).inflate(layoutId, null);
- t.setPosition(
- windowSurfaceControl, xPos, yPos)
- .setWindowCrop(windowSurfaceControl, width + cropPadding, height + cropPadding)
+ t.setPosition(windowSurfaceControl, xPos, yPos)
+ .setWindowCrop(windowSurfaceControl, width, height)
+ .setShadowRadius(windowSurfaceControl, shadowRadius)
+ .setCornerRadius(windowSurfaceControl, cornerRadius)
.show(windowSurfaceControl);
final WindowManager.LayoutParams lp =
new WindowManager.LayoutParams(width, height,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
new file mode 100644
index 0000000..d01a0ee
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 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.wm.shell.flicker.appcompat
+
+import android.content.Context
+import android.system.helpers.CommandsHelper
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import com.android.wm.shell.flicker.BaseTest
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.helpers.LetterboxAppHelper
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.legacy.IFlickerTestData
+import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
+import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
+import org.junit.Assume
+import org.junit.Before
+import org.junit.runners.Parameterized
+
+abstract class BaseAppCompat(flicker: FlickerTest) : BaseTest(flicker) {
+ protected val context: Context = instrumentation.context
+ protected val letterboxApp = LetterboxAppHelper(instrumentation)
+ lateinit var cmdHelper: CommandsHelper
+ lateinit var letterboxStyle: HashMap<String, String>
+
+ /** {@inheritDoc} */
+ override val transition: FlickerBuilder.() -> Unit
+ get() = {
+ setup {
+ setStartRotation()
+ letterboxApp.launchViaIntent(wmHelper)
+ setEndRotation()
+ }
+ }
+
+ @Before
+ fun before() {
+ cmdHelper = CommandsHelper.getInstance(instrumentation)
+ Assume.assumeTrue(tapl.isTablet && isIgnoreOrientationRequest())
+ }
+
+ private fun mapLetterboxStyle(): HashMap<String, String> {
+ val res = cmdHelper.executeShellCommand("wm get-letterbox-style")
+ val lines = res.lines()
+ val map = HashMap<String, String>()
+ for (line in lines) {
+ val keyValuePair = line.split(":")
+ if (keyValuePair.size == 2) {
+ val key = keyValuePair[0].trim()
+ map[key] = keyValuePair[1].trim()
+ }
+ }
+ return map
+ }
+
+ private fun isIgnoreOrientationRequest(): Boolean {
+ val res = cmdHelper.executeShellCommand("wm get-ignore-orientation-request")
+ return res != null && res.contains("true")
+ }
+
+ fun IFlickerTestData.setStartRotation() = setRotation(flicker.scenario.startRotation)
+
+ fun IFlickerTestData.setEndRotation() = setRotation(flicker.scenario.endRotation)
+
+ /** Checks that app entering letterboxed state have rounded corners */
+ fun assertLetterboxAppAtStartHasRoundedCorners() {
+ assumeLetterboxRoundedCornersEnabled()
+ flicker.assertLayersStart { this.hasRoundedCorners(letterboxApp) }
+ }
+
+ fun assertLetterboxAppAtEndHasRoundedCorners() {
+ assumeLetterboxRoundedCornersEnabled()
+ flicker.assertLayersEnd { this.hasRoundedCorners(letterboxApp) }
+ }
+
+ /** Only run on tests with config_letterboxActivityCornersRadius != 0 in devices */
+ private fun assumeLetterboxRoundedCornersEnabled() {
+ if (!::letterboxStyle.isInitialized) {
+ letterboxStyle = mapLetterboxStyle()
+ }
+ Assume.assumeTrue(letterboxStyle.getValue("Corner radius") != "0")
+ }
+
+ fun assertLetterboxAppVisibleAtStartAndEnd() {
+ flicker.appWindowIsVisibleAtStart(letterboxApp)
+ flicker.appWindowIsVisibleAtEnd(letterboxApp)
+ }
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.rotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.rotationTests()
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
new file mode 100644
index 0000000..c57100e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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.wm.shell.flicker.appcompat
+
+import android.platform.test.annotations.Postsubmit
+import androidx.test.filters.RequiresDevice
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Test launching app in size compat mode.
+ *
+ * To run this test: `atest WMShellFlickerTests:OpenAppInSizeCompatModeTest`
+ *
+ * Actions:
+ * ```
+ * Rotate non resizable portrait only app to opposite orientation to trigger size compat mode
+ * ```
+ * Notes:
+ * ```
+ * Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [BaseTest]
+ * ```
+ */
+
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+class OpenAppInSizeCompatModeTest(flicker: FlickerTest) : BaseAppCompat(flicker) {
+
+ /** {@inheritDoc} */
+ override val transition: FlickerBuilder.() -> Unit
+ get() = {
+ setup {
+ setStartRotation()
+ letterboxApp.launchViaIntent(wmHelper)
+ }
+ transitions { setEndRotation() }
+ teardown { letterboxApp.exit(wmHelper) }
+ }
+
+ /**
+ * Windows maybe recreated when rotated. Checks that the focus does not change or if it does,
+ * focus returns to [letterboxApp]
+ */
+ @Postsubmit
+ @Test
+ fun letterboxAppFocusedAtEnd() = flicker.assertEventLog { focusChanges(letterboxApp.`package`) }
+
+ @Postsubmit
+ @Test
+ fun letterboxedAppHasRoundedCorners() = assertLetterboxAppAtEndHasRoundedCorners()
+
+ /**
+ * Checks that the [ComponentNameMatcher.ROTATION] layer appears during the transition, doesn't
+ * flicker, and disappears before the transition is complete
+ */
+ @Postsubmit
+ @Test
+ fun rotationLayerAppearsAndVanishes() {
+ flicker.assertLayers {
+ this.isVisible(letterboxApp)
+ .then()
+ .isVisible(ComponentNameMatcher.ROTATION)
+ .then()
+ .isVisible(letterboxApp)
+ .isInvisible(ComponentNameMatcher.ROTATION)
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
new file mode 100644
index 0000000..f111a8d
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 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.wm.shell.flicker.appcompat
+
+import android.platform.test.annotations.Postsubmit
+import androidx.test.filters.RequiresDevice
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.helpers.WindowUtils
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Test restarting app in size compat mode.
+ *
+ * To run this test: `atest WMShellFlickerTests:RestartAppInSizeCompatModeTest`
+ *
+ * Actions:
+ * ```
+ * Rotate app to opposite orientation to trigger size compat mode
+ * Press restart button and wait for letterboxed app to resize
+ * ```
+ * Notes:
+ * ```
+ * Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [BaseTest]
+ * ```
+ */
+
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+class RestartAppInSizeCompatModeTest(flicker: FlickerTest) : BaseAppCompat(flicker) {
+
+ /** {@inheritDoc} */
+ override val transition: FlickerBuilder.() -> Unit
+ get() = {
+ super.transition(this)
+ transitions { letterboxApp.clickRestart(wmHelper) }
+ teardown { letterboxApp.exit(wmHelper) }
+ }
+
+ @Postsubmit
+ @Test
+ fun appVisibleAtStartAndEnd() = assertLetterboxAppVisibleAtStartAndEnd()
+
+ @Postsubmit
+ @Test
+ fun appLayerVisibilityChanges() {
+ flicker.assertLayers {
+ this.isVisible(letterboxApp)
+ .then()
+ .isInvisible(letterboxApp)
+ .then()
+ .isVisible(letterboxApp)
+ }
+ }
+
+ @Postsubmit
+ @Test
+ fun letterboxedAppHasRoundedCorners() = assertLetterboxAppAtStartHasRoundedCorners()
+
+ /** Checks that the visible region of [letterboxApp] is still within display bounds */
+ @Postsubmit
+ @Test
+ fun appWindowRemainInsideVisibleBounds() {
+ val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
+ flicker.assertLayersEnd { visibleRegion(letterboxApp).coversAtMost(displayBounds) }
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
index 85b2fbc..8eb41b4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.tools.common.Rotation
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -34,6 +35,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 270677470)
class PipPinchInTest(flicker: FlickerTest) : PipTransition(flicker) {
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition { transitions { pipApp.pinchInPipWindow(wmHelper, 0.4f, 30) } }
diff --git a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
index fac0461..47a116b 100644
--- a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
@@ -20,6 +20,7 @@
package="com.android.wm.shell.tests">
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.VIBRATE"/>
<application android:debuggable="true" android:largeHeap="true">
<uses-library android:name="android.test.mock" />
diff --git a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
index 27d40b2..aa1b241 100644
--- a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
@@ -24,4 +24,6 @@
<dimen name="test_window_decor_bottom_outset">40dp</dimen>
<dimen name="test_window_decor_shadow_radius">5dp</dimen>
<dimen name="test_window_decor_resize_handle">10dp</dimen>
+ <dimen name="test_caption_menu_shadow_radius">4dp</dimen>
+ <dimen name="test_caption_menu_corner_radius">20dp</dimen>
</resources>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index e8784d7..bc0d93a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -475,6 +475,36 @@
verify(mMockRestartDialogLayout).updateVisibility(true);
}
+ @Test
+ public void testRestartLayoutRecreatedIfNeeded() {
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+ /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ doReturn(true).when(mMockRestartDialogLayout)
+ .needsToBeRecreated(any(TaskInfo.class),
+ any(ShellTaskOrganizer.TaskListener.class));
+
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+ verify(mMockRestartDialogLayout, times(2))
+ .createLayout(anyBoolean());
+ }
+
+ @Test
+ public void testRestartLayoutNotRecreatedIfNotNeeded() {
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+ /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ doReturn(false).when(mMockRestartDialogLayout)
+ .needsToBeRecreated(any(TaskInfo.class),
+ any(ShellTaskOrganizer.TaskListener.class));
+
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+ verify(mMockRestartDialogLayout, times(1))
+ .createLayout(anyBoolean());
+ }
+
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
@CameraCompatControlState int cameraCompatControlState) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index b6dbcf2..523cb66 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -48,7 +48,6 @@
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -82,7 +81,7 @@
@Mock
private ShellExecutor mMainExecutor;
@Mock
- private SplitScreenController mSplitScreenController;
+ private WindowManager mWindowManager;
private DragAndDropController mController;
@@ -100,11 +99,6 @@
}
@Test
- public void instantiateController_registerConfigChangeListener() {
- verify(mShellController, times(1)).addConfigurationChangeListener(any());
- }
-
- @Test
public void testIgnoreNonDefaultDisplays() {
final int nonDefaultDisplayId = 12345;
final View dragLayout = mock(View.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index ed0ac5f..3901dab 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -284,41 +284,6 @@
@Test
@UiThreadTest
- public void testDismissFromBeingOccluded() {
- enterSplit();
-
- ActivityManager.RunningTaskInfo normalTask = new TestRunningTaskInfoBuilder()
- .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
- .build();
-
- // Create a request to bring a normal task forward
- TransitionRequestInfo request =
- new TransitionRequestInfo(TRANSIT_TO_FRONT, normalTask, null);
- IBinder transition = mock(IBinder.class);
- WindowContainerTransaction result = mStageCoordinator.handleRequest(transition, request);
-
- assertTrue(containsSplitExit(result));
-
- // make sure we haven't made any local changes yet (need to wait until transition is ready)
- assertTrue(mStageCoordinator.isSplitScreenVisible());
-
- // simulate the transition
- TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT, 0)
- .addChange(TRANSIT_TO_FRONT, normalTask)
- .addChange(TRANSIT_TO_BACK, mMainChild)
- .addChange(TRANSIT_TO_BACK, mSideChild)
- .build();
- mMainStage.onTaskVanished(mMainChild);
- mSideStage.onTaskVanished(mSideChild);
- mStageCoordinator.startAnimation(transition, info,
- mock(SurfaceControl.Transaction.class),
- mock(SurfaceControl.Transaction.class),
- mock(Transitions.TransitionFinishCallback.class));
- assertFalse(mStageCoordinator.isSplitScreenVisible());
- }
-
- @Test
- @UiThreadTest
public void testDismissFromMultiWindowSupport() {
enterSplit();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 0bb809d..2e2e49e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -134,6 +134,7 @@
when(mSplitLayout.getBounds2()).thenReturn(mBounds2);
when(mSplitLayout.getRootBounds()).thenReturn(mRootBounds);
when(mSplitLayout.isLandscape()).thenReturn(false);
+ when(mSplitLayout.applyTaskChanges(any(), any(), any())).thenReturn(true);
mRootTask = new TestRunningTaskInfoBuilder().build();
mRootLeash = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 3550721..1d1aa79 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -49,6 +49,7 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopTasksController;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +74,7 @@
@Mock private Choreographer mMainChoreographer;
@Mock private ShellTaskOrganizer mTaskOrganizer;
@Mock private DisplayController mDisplayController;
+ @Mock private SplitScreenController mSplitScreenController;
@Mock private SyncTransactionQueue mSyncQueue;
@Mock private DesktopModeController mDesktopModeController;
@Mock private DesktopTasksController mDesktopTasksController;
@@ -98,6 +100,7 @@
mSyncQueue,
Optional.of(mDesktopModeController),
Optional.of(mDesktopTasksController),
+ Optional.of(mSplitScreenController),
mDesktopModeWindowDecorFactory,
mMockInputMonitorFactory
);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index b80edce..7e39b5b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -108,6 +108,8 @@
private SurfaceControl.Transaction mMockSurfaceControlAddWindowT;
private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
private int mCaptionMenuWidthId;
+ private int mCaptionMenuShadowRadiusId;
+ private int mCaptionMenuCornerRadiusId;
@Before
public void setUp() {
@@ -118,6 +120,8 @@
mRelayoutParams.mLayoutResId = 0;
mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height;
mCaptionMenuWidthId = R.dimen.test_freeform_decor_caption_menu_width;
+ mCaptionMenuShadowRadiusId = R.dimen.test_caption_menu_shadow_radius;
+ mCaptionMenuCornerRadiusId = R.dimen.test_caption_menu_corner_radius;
mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
@@ -431,7 +435,19 @@
verify(additionalWindowSurfaceBuilder).setParent(decorContainerSurface);
verify(additionalWindowSurfaceBuilder).build();
verify(mMockSurfaceControlAddWindowT).setPosition(additionalWindowSurface, 20, 40);
- verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, 442, 74);
+ final int width = WindowDecoration.loadDimensionPixelSize(
+ mContext.getResources(), mCaptionMenuWidthId);
+ final int height = WindowDecoration.loadDimensionPixelSize(
+ mContext.getResources(), mRelayoutParams.mCaptionHeightId);
+ verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, width, height);
+ final int shadowRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+ mCaptionMenuShadowRadiusId);
+ verify(mMockSurfaceControlAddWindowT)
+ .setShadowRadius(additionalWindowSurface, shadowRadius);
+ final int cornerRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+ mCaptionMenuCornerRadiusId);
+ verify(mMockSurfaceControlAddWindowT)
+ .setCornerRadius(additionalWindowSurface, cornerRadius);
verify(mMockSurfaceControlAddWindowT).show(additionalWindowSurface);
verify(mMockSurfaceControlViewHostFactory, Mockito.times(2))
.create(any(), eq(defaultDisplay), any());
@@ -559,13 +575,15 @@
int y = mRelayoutParams.mCaptionY;
int width = loadDimensionPixelSize(resources, mCaptionMenuWidthId);
int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
+ int shadowRadius = loadDimensionPixelSize(resources, mCaptionMenuShadowRadiusId);
+ int cornerRadius = loadDimensionPixelSize(resources, mCaptionMenuCornerRadiusId);
String name = "Test Window";
WindowDecoration.AdditionalWindow additionalWindow =
addWindow(R.layout.desktop_mode_decor_handle_menu, name,
mMockSurfaceControlAddWindowT,
x - mRelayoutResult.mDecorContainerOffsetX,
y - mRelayoutResult.mDecorContainerOffsetY,
- width, height, 10);
+ width, height, shadowRadius, cornerRadius);
return additionalWindow;
}
}
diff --git a/libs/androidfw/ApkParsing.cpp b/libs/androidfw/ApkParsing.cpp
index 32d2c5b..7eedfdb 100644
--- a/libs/androidfw/ApkParsing.cpp
+++ b/libs/androidfw/ApkParsing.cpp
@@ -56,6 +56,11 @@
return nullptr;
}
+ // Make sure file starts with 'lib/' prefix.
+ if (strncmp(fileName, APK_LIB.data(), APK_LIB_LEN) != 0) {
+ return nullptr;
+ }
+
// Make sure there aren't subdirectories by checking if the next / after lib/ is the last slash
if (memchr(fileName + APK_LIB_LEN, '/', fileNameLen - APK_LIB_LEN) != lastSlash) {
return nullptr;
diff --git a/libs/androidfw/tests/ApkParsing_test.cpp b/libs/androidfw/tests/ApkParsing_test.cpp
index 62e88c6..ac1dc9b 100644
--- a/libs/androidfw/tests/ApkParsing_test.cpp
+++ b/libs/androidfw/tests/ApkParsing_test.cpp
@@ -74,4 +74,10 @@
auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false);
ASSERT_THAT(lastSlash, IsNull());
}
+
+TEST(ApkParsingTest, InvalidPrefix) {
+ const char* path = "assets/libhello.so";
+ auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false);
+ ASSERT_THAT(lastSlash, IsNull());
+}
}
\ No newline at end of file
diff --git a/libs/dream/OWNERS b/libs/dream/OWNERS
new file mode 100644
index 0000000..a4b0127
--- /dev/null
+++ b/libs/dream/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/dreams/OWNERS
\ No newline at end of file
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index ecf6cfc..b3eaa0c 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -463,6 +463,13 @@
if (hasGainmap() && format == JavaCompressFormat::Jpeg) {
SkBitmap baseBitmap = getSkBitmap();
SkBitmap gainmapBitmap = gainmap()->bitmap->getSkBitmap();
+ if (gainmapBitmap.colorType() == SkColorType::kAlpha_8_SkColorType) {
+ SkBitmap greyGainmap;
+ auto greyInfo = gainmapBitmap.info().makeColorType(SkColorType::kGray_8_SkColorType);
+ greyGainmap.setInfo(greyInfo, gainmapBitmap.rowBytes());
+ greyGainmap.setPixelRef(sk_ref_sp(gainmapBitmap.pixelRef()), 0, 0);
+ gainmapBitmap = std::move(greyGainmap);
+ }
SkJpegEncoder::Options options{.fQuality = quality};
return SkJpegGainmapEncoder::EncodeHDRGM(stream, baseBitmap.pixmap(), options,
gainmapBitmap.pixmap(), options, gainmap()->info);
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index c6f32c2..88f00dc 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -123,6 +123,21 @@
@Retention(RetentionPolicy.SOURCE)
public @interface SubHalPowerCapabilityFlags {}
+ /** The capability is unknown to be supported or not. */
+ public static final int CAPABILITY_UNKNOWN = 0;
+ /** The capability is supported. */
+ public static final int CAPABILITY_SUPPORTED = 1;
+ /** The capability is not supported. */
+ public static final int CAPABILITY_UNSUPPORTED = 2;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"CAPABILITY_"}, value = {CAPABILITY_UNKNOWN,
+ CAPABILITY_SUPPORTED,
+ CAPABILITY_UNSUPPORTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CapabilitySupportType {}
+
+
/**
* Returns an empty GnssCapabilities object.
*
@@ -375,30 +390,25 @@
}
/**
- * Returns {@code true} if GNSS chipset supports accumulated delta range, {@code false}
- * otherwise.
- *
- * <p>The value is only known if {@link #isAccumulatedDeltaRangeCapabilityKnown()} is
- * true.
+ * Returns {@link #CAPABILITY_SUPPORTED} if GNSS chipset supports accumulated delta
+ * range, {@link #CAPABILITY_UNSUPPORTED} if GNSS chipset does not support accumulated
+ * delta range, and {@link #CAPABILITY_UNKNOWN} if it is unknown, which means GNSS
+ * chipset may or may not support accumulated delta range.
*
* <p>The accumulated delta range information can be queried in
* {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeState()},
* {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeMeters()}, and
* {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeUncertaintyMeters()}.
*/
- public boolean hasAccumulatedDeltaRange() {
+ public @CapabilitySupportType int hasAccumulatedDeltaRange() {
if (!mIsAdrCapabilityKnown) {
- throw new IllegalStateException("Accumulated delta range capability is unknown.");
+ return CAPABILITY_UNKNOWN;
}
- return (mTopFlags & TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE) != 0;
- }
-
- /**
- * Returns {@code true} if {@link #hasAccumulatedDeltaRange()} is known, {@code false}
- * otherwise.
- */
- public boolean isAccumulatedDeltaRangeCapabilityKnown() {
- return mIsAdrCapabilityKnown;
+ if ((mTopFlags & TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE) != 0) {
+ return CAPABILITY_SUPPORTED;
+ } else {
+ return CAPABILITY_UNSUPPORTED;
+ }
}
/**
@@ -597,9 +607,9 @@
if (hasMeasurementCorrectionsForDriving()) {
builder.append("MEASUREMENT_CORRECTIONS_FOR_DRIVING ");
}
- if (mIsAdrCapabilityKnown && hasAccumulatedDeltaRange()) {
+ if (hasAccumulatedDeltaRange() == CAPABILITY_SUPPORTED) {
builder.append("ACCUMULATED_DELTA_RANGE ");
- } else if (!mIsAdrCapabilityKnown) {
+ } else if (hasAccumulatedDeltaRange() == CAPABILITY_UNKNOWN) {
builder.append("ACCUMULATED_DELTA_RANGE(unknown) ");
}
if (hasMeasurementCorrectionsLosSats()) {
@@ -795,19 +805,17 @@
/**
* Sets accumulated delta range capability.
*/
- public @NonNull Builder setHasAccumulatedDeltaRange(boolean capable) {
- mIsAdrCapabilityKnown = true;
- mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE,
- capable);
- return this;
- }
-
- /**
- * Clears accumulated delta range capability and sets it as unknown.
- */
- public @NonNull Builder clearIsAccumulatedDeltaRangeCapabilityKnown() {
- mIsAdrCapabilityKnown = false;
- mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+ public @NonNull Builder setHasAccumulatedDeltaRange(@CapabilitySupportType int capable) {
+ if (capable == CAPABILITY_UNKNOWN) {
+ mIsAdrCapabilityKnown = false;
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+ } else if (capable == CAPABILITY_SUPPORTED) {
+ mIsAdrCapabilityKnown = true;
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, true);
+ } else if (capable == CAPABILITY_UNSUPPORTED) {
+ mIsAdrCapabilityKnown = true;
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+ }
return this;
}
diff --git a/packages/AppPredictionLib/Android.bp b/packages/AppPredictionLib/Android.bp
index 5a68fdc..31c1936 100644
--- a/packages/AppPredictionLib/Android.bp
+++ b/packages/AppPredictionLib/Android.bp
@@ -25,7 +25,7 @@
name: "app_prediction",
sdk_version: "system_current",
- min_sdk_version: "system_current",
+ min_sdk_version: "current",
srcs: [
"src/**/*.java",
diff --git a/packages/CarrierDefaultApp/res/values-af/strings.xml b/packages/CarrierDefaultApp/res/values-af/strings.xml
index 13ae4da..cb911d8 100644
--- a/packages/CarrierDefaultApp/res/values-af/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-af/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Gaan in elk geval deur blaaier voort"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestasiehupstoot"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter jou 5G-ervaring"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveel aan dat jy ’n werkverrigtinghupstootpakket koop. Tik om deur %2$s te koop."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie nou nie"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Bestuur"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop ’n prestasiehupstoot."</string>
diff --git a/packages/CarrierDefaultApp/res/values-am/strings.xml b/packages/CarrierDefaultApp/res/values-am/strings.xml
index e1f91ce..edaa248 100644
--- a/packages/CarrierDefaultApp/res/values-am/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-am/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"የአፈጻጸም ጭማሪ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"የእርስዎን የ5ጂ ተሞክሮ ያሻሽሉ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s የአፈጻጸም መጨመሪያ ዕቅድ መግዛትን ይመክራል። በ%2$s ለመግዛት መታ ያድርጉ።"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"አሁን አይደለም"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"አስተዳድር"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"የአፈጻጸም ጭማሪ ይግዙ።"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ar/strings.xml b/packages/CarrierDefaultApp/res/values-ar/strings.xml
index c2e5ba8..9bc5e45 100644
--- a/packages/CarrierDefaultApp/res/values-ar/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ar/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المؤسسة المعروضة."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"المتابعة على أي حال عبر المتصفح"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"تطبيق تعزيز الأداء"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"تحسين تجربة شبكة الجيل الخامس"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"هناك اقتراح من \"%1$s\" لشراء خطة لتعزيز الأداء. انقر للشراء من خلال \"%2$s\"."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"لاحقًا"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"إدارة"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"شراء تطبيق تعزيز الأداء"</string>
diff --git a/packages/CarrierDefaultApp/res/values-as/strings.xml b/packages/CarrierDefaultApp/res/values-as/strings.xml
index 8881940..732c52d 100644
--- a/packages/CarrierDefaultApp/res/values-as/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-as/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"উদাহৰণস্বৰূপে, আপোনাক দেখুওৱা লগ ইনৰ পৃষ্ঠাটো প্ৰতিষ্ঠানটোৰ নিজা নহ\'বও পাৰে।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"তথাপিও ব্ৰাউজাৰৰ জৰিয়তে অব্যাহত ৰাখক"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"কাৰ্যক্ষমতা পৰিৱৰ্ধন"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"আপোনাৰ 5G অভিজ্ঞতা উন্নত কৰক"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$sএ এখন কাৰ্যক্ষমতা পৰিৱৰ্ধন অঁচনি ক্ৰয় কৰাৰ চুপাৰিছ কৰে। %2$sৰ জৰিয়তে ক্ৰয় কৰিবলৈ টিপক।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এতিয়া নহয়"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"পৰিচালনা কৰক"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"এটা কাৰ্যক্ষমতা পৰিৱৰ্ধন ক্ৰয় কৰক।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-az/strings.xml b/packages/CarrierDefaultApp/res/values-az/strings.xml
index f64fcb6..05c300f 100644
--- a/packages/CarrierDefaultApp/res/values-az/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-az/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Məsələn, giriş səhifəsi göstərilən təşkilata aid olmaya bilər."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Hər bir halda brazuer ilə davam edin"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artırması"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G təcrübənizi təkmilləşdirin"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s performans artırma planı almağı tövsiyə edir. %2$s ilə almaq üçün toxunun."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"İndi yox"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"İdarə edin"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artırması alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
index 5533bfd..deeb5c7 100644
--- a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na primer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko pregledača"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje učinka"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte 5G doživljaj"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da biste kupili preko %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljaj"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje učinka."</string>
diff --git a/packages/CarrierDefaultApp/res/values-be/strings.xml b/packages/CarrierDefaultApp/res/values-be/strings.xml
index 0053cda..4f820ca 100644
--- a/packages/CarrierDefaultApp/res/values-be/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-be/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Напрыклад, старонка ўваходу можа не належаць указанай арганізацыі."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Усё роўна працягнуць праз браўзер"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Павышэнне прадукцыйнасці"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Пашырце магчымасці 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рэкамендуе купіць план павышэння прадукцыйнасці. Націсніце, каб купіць праз %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не цяпер"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Кіраваць"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Аплаціце павышэнне прадукцыйнасці."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bg/strings.xml b/packages/CarrierDefaultApp/res/values-bg/strings.xml
index a37e0a3..a32c632 100644
--- a/packages/CarrierDefaultApp/res/values-bg/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bg/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Например страницата за вход може да не принадлежи на показаната организация."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Продължаване през браузър въпреки това"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Увеличаване на ефективността"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобряване на практическата работа с 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоръчва да купите план за увеличаване на ефективността. Докоснете, за да купите чрез %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управление"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете пакет за увеличаване на ефективността."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml
index f78449c..ac4fab4 100644
--- a/packages/CarrierDefaultApp/res/values-bn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগ-ইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"যাই হোক, ব্রাউজারের মাধ্যমে চালিয়ে যান"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"পারফর্ম্যান্স বুস্ট"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"আপনার 5G অভিজ্ঞতা উন্নত করুন"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s পারফর্ম্যান্স বুস্ট প্ল্যান কেনার সাজেশন দেয়। %2$s-এর মাধ্যমে কিনতে ট্যাপ করুন।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এখন নয়"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ম্যানেজ করুন"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"পারফর্ম্যান্স বুস্ট সংক্রান্ত ফিচার কিনুন।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
index 7be8e2b..cc59f9db 100644
--- a/packages/CarrierDefaultApp/res/values-bs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Naprimjer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko preglednika"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pojačavanje performansi"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte iskustvo s 5G mrežom"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da kupite koristeći %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite pojačavanje performansi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
index 54c9e6e..ded2263 100644
--- a/packages/CarrierDefaultApp/res/values-ca/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua igualment mitjançant el navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimització de rendiment"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Millora l\'experiència 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomana comprar un pla d\'optimització de rendiment. Toca per comprar-lo mitjançant %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ara no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestiona"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra una optimització de rendiment."</string>
diff --git a/packages/CarrierDefaultApp/res/values-cs/strings.xml b/packages/CarrierDefaultApp/res/values-cs/strings.xml
index 8a09421..d21c500 100644
--- a/packages/CarrierDefaultApp/res/values-cs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-cs/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Přihlašovací stránka například nemusí patřit zobrazované organizaci."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Přesto pokračovat prostřednictvím prohlížeče"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšení výkonu"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Získejte rychlejší připojení 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s doporučuje zakoupit zvýšení výkonu. Klepnutím ho zakoupíte přes operátora %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teď ne"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovat"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupte si zvýšení výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-da/strings.xml b/packages/CarrierDefaultApp/res/values-da/strings.xml
index cd411c9..192036d 100644
--- a/packages/CarrierDefaultApp/res/values-da/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-da/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsæt alligevel via browseren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ydeevneboost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-oplevelse"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler, at du køber et abonnement med ydeevneboost. Tryk for at købe via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Køb et ydeevneboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-de/strings.xml b/packages/CarrierDefaultApp/res/values-de/strings.xml
index d20a1e8..0226d9f 100644
--- a/packages/CarrierDefaultApp/res/values-de/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-de/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Trotzdem in einem Browser fortfahren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Leistungs-Boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-Nutzung verbessern"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s empfiehlt den Kauf eines Tarifs mit Leistungs-Boost. Du kannst tippen, um über %2$s einen zu kaufen."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nicht jetzt"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Verwalten"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Leistungs-Boost erwerben."</string>
diff --git a/packages/CarrierDefaultApp/res/values-el/strings.xml b/packages/CarrierDefaultApp/res/values-el/strings.xml
index 0759011..96e3eb3 100644
--- a/packages/CarrierDefaultApp/res/values-el/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-el/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ενίσχυση απόδοσης"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Βελτιώστε την εμπειρία 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"Το %1$s προτείνει την αγορά ενός προγράμματος ενίσχυσης απόδοσης. Πατήστε για αγορά μέσω %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Όχι τώρα"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Διαχείριση"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Αγοράστε μια ενίσχυση απόδοσης."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
index 720dbc7..aac44fc 100644
--- a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
index 87978ac..d8ec210 100644
--- a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
@@ -15,8 +15,8 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page may not belong to the organization shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+ <string name="performance_boost_notification_detail" msgid="86969987181456032">"Tap to visit %s\'s website and learn more."</string>
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
index 720dbc7..aac44fc 100644
--- a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
index 720dbc7..aac44fc 100644
--- a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
index 7324a5b..87b007f 100644
--- a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
@@ -15,8 +15,8 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page may not belong to the organization shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+ <string name="performance_boost_notification_detail" msgid="86969987181456032">"Tap to visit %s\'s website and learn more."</string>
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
index fedf1ac..1ad7751 100644
--- a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos desde el navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de rendimiento"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia de 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda que compres un plan de aumento de rendimiento. Presiona para comprar mediante %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra un aumento de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-es/strings.xml b/packages/CarrierDefaultApp/res/values-es/strings.xml
index 85642b8..972afa9 100644
--- a/packages/CarrierDefaultApp/res/values-es/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos a través del navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mejora de rendimiento"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda comprar un plan de mejora del rendimiento. Toca para comprarlo mediante %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar una mejora de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-et/strings.xml b/packages/CarrierDefaultApp/res/values-et/strings.xml
index 769f240..1ac991c 100644
--- a/packages/CarrierDefaultApp/res/values-et/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-et/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jätka siiski brauseris"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Jõudluse võimendus"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Täiustage oma 5G-kogemust"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s soovitab osta jõudluse võimendusega paketi. Puudutage teenuse %2$s kaudu ostmiseks."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Mitte praegu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Haldamine"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Ostke jõudluse võimendus."</string>
diff --git a/packages/CarrierDefaultApp/res/values-eu/strings.xml b/packages/CarrierDefaultApp/res/values-eu/strings.xml
index 7274bce..fedf29d 100644
--- a/packages/CarrierDefaultApp/res/values-eu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-eu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Adibidez, baliteke saioa hasteko orria adierazitako erakundearena ez izatea."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jarraitu arakatzailearen bidez, halere"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Errendimendu-hobekuntza"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Hobetu 5G bidezko konexioa"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s zerbitzuak errendimendua hobetzeko kidetza bat erostea gomendatzen du. Sakatu hau %2$s bidez erosteko."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Orain ez"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kudeatu"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Erosi errendimendu-hobekuntza bat."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index 2cbe297..a9ac157 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"درهر صورت ازطریق مرورگر ادامه یابد"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"تقویتکننده عملکرد"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"تجربه نسل پنجم شبکه تلفن همراه را بهبود دهید"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s توصیه میکند طرح تقویت عملکرد خریداری شود. برای خرید ازطریق %2$s، ضربه بزنید."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"اکنون نه"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"مدیریت"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"تقویتکننده عملکرد خریداری کنید."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fi/strings.xml b/packages/CarrierDefaultApp/res/values-fi/strings.xml
index 1a388cd..e0bf1e7 100644
--- a/packages/CarrierDefaultApp/res/values-fi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jatka selaimen kautta"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Suorituskykyboosti"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Paranna 5G-kokemusta"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s suosittelee suorituskykyboostipaketin ostamista. Napauta ja tee ostos operaattorilla %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ei nyt"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Muuta"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Osta suorituskykyboosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
index ad6c794..a56a4db 100644
--- a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion pourrait ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans un navigateur"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimiseur de performances"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience de la 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Touchez pour acheter par l\'intermédiaire de %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Plus tard"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un optimiseur de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr/strings.xml b/packages/CarrierDefaultApp/res/values-fr/strings.xml
index 92b47be..699d4b3 100644
--- a/packages/CarrierDefaultApp/res/values-fr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans le navigateur"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performances"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Appuyez pour acheter via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Pas maintenant"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un boost de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gl/strings.xml b/packages/CarrierDefaultApp/res/values-gl/strings.xml
index 2c1be52..b252b8c 100644
--- a/packages/CarrierDefaultApp/res/values-gl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, é posible que a páxina de inicio de sesión non pertenza á organización que se mostra."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar igualmente co navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mellora de rendemento"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Mellora a túa experiencia 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar un plan de mellora do rendemento. Toca para realizar a compra a través de %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora non"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Xestionar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar unha mellora de rendemento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gu/strings.xml b/packages/CarrierDefaultApp/res/values-gu/strings.xml
index af09d13..8f1174a 100644
--- a/packages/CarrierDefaultApp/res/values-gu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ઉદાહરણ તરીકે, લોગિન પૃષ્ઠ બતાવવામાં આવેલી સંસ્થાનું ન પણ હોય."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"તો પણ બ્રાઉઝર મારફતે ચાલુ રાખો"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"પર્ફોર્મન્સ બૂસ્ટ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"તમારા 5G અનુભવને બહેતર બનાવો"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s પર્ફોર્મન્સ બૂસ્ટ પ્લાન ખરીદવાનો સુઝાવ આપે છે. %2$s મારફતે ખરીદવા માટે ટૅપ કરો."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"હમણાં નહીં"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"મેનેજ કરો"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"પર્ફોર્મન્સ બૂસ્ટ ખરીદો."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hi/strings.xml b/packages/CarrierDefaultApp/res/values-hi/strings.xml
index e51b1a9..52da322 100644
--- a/packages/CarrierDefaultApp/res/values-hi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरण के लिए, हो सकता है कि लॉगिन पेज दिखाए गए संगठन का ना हो."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ब्राउज़र के ज़रिए किसी भी तरह जारी रखें"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफ़ॉर्मेंस बूस्ट"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G का बेहतर अनुभव पाएं"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, परफ़ॉर्मेंस को बेहतर बनाने वाले प्लान को खरीदने का सुझाव देता है. %2$s से प्लान खरीदने के लिए टैप करें."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अभी नहीं"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"मैनेज करें"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"कोई परफ़ॉर्मेंस बूस्ट खरीदें."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hr/strings.xml b/packages/CarrierDefaultApp/res/values-hr/strings.xml
index 5a22ad5..1b60123 100644
--- a/packages/CarrierDefaultApp/res/values-hr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi putem preglednika"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje izvedbe"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte svoj 5G doživljaj"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupnju paketa za poboljšanje izvedbe. Dodirnite da biste kupili putem usluge %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sad"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje izvedbe."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hu/strings.xml b/packages/CarrierDefaultApp/res/values-hu/strings.xml
index a841cb2..026586b 100644
--- a/packages/CarrierDefaultApp/res/values-hu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Például lehetséges, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Folytatás ennek ellenére böngészőn keresztül"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Teljesítménynövelés"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Az 5G-élmény javítása"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"A(z) %1$s teljesítménynövelő csomag vásárlását javasolja. Koppintson a(z) %2$s szolgáltatón keresztüli vásárláshoz."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Most nem"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kezelés"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Vásároljon teljesítménynövelést."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hy/strings.xml b/packages/CarrierDefaultApp/res/values-hy/strings.xml
index 49fbece..dc93d6e 100644
--- a/packages/CarrierDefaultApp/res/values-hy/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hy/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Օրինակ՝ մուտքի էջը կարող է ցուցադրված կազմակերպության էջը չլինել:"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Շարունակել դիտարկիչի միջոցով"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Արտադրողականության բարձրացում"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Բարելավեք 5G-ի օգտագործման ձեր փորձառությունը"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s օպերատորը խորհուրդ է տալիս ձեռք բերել արդյունավետությունը բարձրացնող սակագնային պլան։ Հպեք՝ %2$s-ի միջոցով գնելու համար։"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ոչ հիմա"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Կառավարել"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Բարձրացրեք ցանցի արտադրողականությունը վճարի դիմաց։"</string>
diff --git a/packages/CarrierDefaultApp/res/values-in/strings.xml b/packages/CarrierDefaultApp/res/values-in/strings.xml
index 170bd76..56b8b2e 100644
--- a/packages/CarrierDefaultApp/res/values-in/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-in/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Misalnya, halaman login mungkin bukan milik organisasi yang ditampilkan."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Tetap lanjutkan melalui browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Penguat sinyal"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G Anda"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s merekomendasikan pembelian paket penguat sinyal. Ketuk untuk membeli melalui %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Lain kali"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kelola"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli penguat sinyal."</string>
diff --git a/packages/CarrierDefaultApp/res/values-is/strings.xml b/packages/CarrierDefaultApp/res/values-is/strings.xml
index 8684ee6..510d5fd 100644
--- a/packages/CarrierDefaultApp/res/values-is/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-is/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Til dæmis getur verið að innskráningarsíðan tilheyri ekki fyrirtækinu sem birtist."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Halda samt áfram í vafra"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Afkastaaukning"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Bættu upplifun þína af 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mælir með að kaupa áskrift sem eykur afköst. Ýttu til að kaupa í gegnum %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ekki núna"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Stjórna"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kaupa afkastaaukningu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-it/strings.xml b/packages/CarrierDefaultApp/res/values-it/strings.xml
index ea88457..324aa4f 100644
--- a/packages/CarrierDefaultApp/res/values-it/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-it/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua comunque dal browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento di prestazioni"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Migliora la tua esperienza 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s consiglia l\'acquisto di un piano di miglioramento delle prestazioni. Tocca per acquistare tramite %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Non ora"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestisci"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Acquista un aumento di prestazioni."</string>
diff --git a/packages/CarrierDefaultApp/res/values-iw/strings.xml b/packages/CarrierDefaultApp/res/values-iw/strings.xml
index c7229ba..9e2f31c 100644
--- a/packages/CarrierDefaultApp/res/values-iw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-iw/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"המשך בכל זאת באמצעות דפדפן"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"שיפור ביצועים"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"שיפור חווית השימוש ב-5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"יש המלצה של %1$s לקנות תוכנית לשיפור הביצועים. אפשר להקיש כדי לקנות דרך %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"לא עכשיו"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ניהול"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"רכישת שיפור ביצועים."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ja/strings.xml b/packages/CarrierDefaultApp/res/values-ja/strings.xml
index 2fd86c8..833f8a5 100644
--- a/packages/CarrierDefaultApp/res/values-ja/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ja/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ブラウザから続行"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"パフォーマンス ブースト"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G のエクスペリエンスを改善"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s さんがパフォーマンス ブースト プランの購入をおすすめしています。%2$sまでにタップして購入しましょう。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"後で"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"パフォーマンス ブーストを購入してください。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ka/strings.xml b/packages/CarrierDefaultApp/res/values-ka/strings.xml
index 76f7273..507e0d9 100644
--- a/packages/CarrierDefaultApp/res/values-ka/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ka/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"მაგალითად, სისტემაში შესვლის გვერდი შეიძლება არ ეკუთვნოდეს ნაჩვენებ ორგანიზაციას."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"მაინც ბრაუზერში გაგრძელება"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ეფექტურობის გაძლიერება"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"გააუმჯობესეთ თქვენი 5G გამოცდილება"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s-ის მიერ რეკომენდებულია ეფექტურობის გაძლიერების გეგმის შეძენა. შეეხეთ %2$s-ის დახმარებით შესაძენად."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ახლა არა"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"მართვა"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ეფექტურობის გაძლიერების შეძენა."</string>
diff --git a/packages/CarrierDefaultApp/res/values-kk/strings.xml b/packages/CarrierDefaultApp/res/values-kk/strings.xml
index 4a895f4..32eae44 100644
--- a/packages/CarrierDefaultApp/res/values-kk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Мысалы, кіру беті көрсетілген ұйымға тиесілі болмауы мүмкін."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Бәрібір браузер арқылы жалғастыру"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Өнімділікті арттыру"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G желісімен жұмысыңызды жақсартыңыз"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s өнімділікті арттыру жоспарын сатып алуды ұсынады. %2$s операторынан сатып алу үшін түртіңіз."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Қазір емес"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Басқару"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Өнімділікті арттыру құралын сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-km/strings.xml b/packages/CarrierDefaultApp/res/values-km/strings.xml
index 51a51ff..531226f 100644
--- a/packages/CarrierDefaultApp/res/values-km/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-km/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ឧទាហរណ៍៖ ទំព័រចូលនេះអាចនឹងមិនមែនជាកម្មសិទ្ធិរបស់ស្ថាប័នដែលបានបង្ហាញនេះទេ។"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"យ៉ាងណាក៏ដោយនៅតែបន្តតាមរយៈកម្មវិធីរុករកតាមអ៊ីនធឺណិត"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ការបង្កើនប្រតិបត្តិការ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"កែលម្អបទពិសោធន៍ប្រើ 5G របស់អ្នក"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ណែនាំឱ្យទិញផែនការជំរុញប្រតិបត្តិការ។ ចុចដើម្បីទិញតាមរយៈ %2$s។"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"កុំទាន់"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"គ្រប់គ្រង"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ទិញការបង្កើនប្រតិបត្តិការ។"</string>
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
index c97d6f0..4335d0c 100644
--- a/packages/CarrierDefaultApp/res/values-kn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ಉದಾಹರಣೆಗೆ, ಲಾಗಿನ್ ಪುಟವು ತೋರಿಸಲಾಗಿರುವ ಸಂಸ್ಥೆಗೆ ಸಂಬಂಧಿಸಿಲ್ಲದಿರಬಹುದು."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ಪರವಾಗಿಲ್ಲ, ಬ್ರೌಸರ್ ಮೂಲಕ ಮುಂದುವರಿಸಿ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ನಿಮ್ಮ 5G ಅನುಭವವನ್ನು ಸುಧಾರಿಸಿ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಹೆಚ್ಚಿಸುವ ಪ್ಲಾನ್ ಅನ್ನು ಖರೀದಿಸಲು %1$s ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ. %2$s ಮೂಲಕ ಖರೀದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ಈಗ ಬೇಡ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ನಿರ್ವಹಿಸಿ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್ ಅನ್ನು ಖರೀದಿಸಿ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ko/strings.xml b/packages/CarrierDefaultApp/res/values-ko/strings.xml
index 395627d..3bb5628 100644
--- a/packages/CarrierDefaultApp/res/values-ko/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ko/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"브라우저를 통해 계속하기"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"성능 향상"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G 사용 환경 개선"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s에서 성능 향상 계획 구매를 추천합니다. %2$s을(를) 통해 구매하려면 탭하세요."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"나중에"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"관리"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"성능 향상 구매"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
index b3970e3..07bb618 100644
--- a/packages/CarrierDefaultApp/res/values-ky/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, аккаунтка кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Баары бир серепчи аркылуу улантуу"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Иштин майнаптуулугун жогорулатуу"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G менен оңой иштеңиз"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s майнаптуулугун жогорулата турган тарифтик планды сатып алууну сунуштайт. %2$s аркылуу сатып алуу үчүн таптаңыз."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Азыр эмес"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Тескөө"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Иштин майнаптуулугун жогорулатууну сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lo/strings.xml b/packages/CarrierDefaultApp/res/values-lo/strings.xml
index 70d8888..480a7ce 100644
--- a/packages/CarrierDefaultApp/res/values-lo/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lo/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ຕົວຢ່າງ, ໜ້າເຂົ້າສູ່ລະບົບອາດຈະບໍ່ແມ່ນຂອງອົງກອນທີ່ປາກົດ."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ດຳເນີນການຕໍ່ຜ່ານໂປຣແກຣມທ່ອງເວັບ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ເລັ່ງປະສິດທິພາບ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ປັບປຸງປະສົບການ 5G ຂອງທ່ານ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ແນະນຳໃຫ້ຊື້ແຜນການເລັ່ງປະສິດທິພາບ. ແຕະເພື່ອຊື້ຜ່ານ %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ບໍ່ຟ້າວເທື່ອ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ຈັດການ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ຊື້ການເລັ່ງປະສິດທິພາບ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lt/strings.xml b/packages/CarrierDefaultApp/res/values-lt/strings.xml
index 8068416..1f4a433 100644
--- a/packages/CarrierDefaultApp/res/values-lt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lt/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vis tiek tęsti naudojant naršyklę"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Našumo pagerinimas"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagerinkite 5G ryšį"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"„%1$s“ rekomenduoja įsigyti našumo pagerinimo planą. Palieskite, kad įsigytumėte naudodamiesi „%2$s“ paslaugomis."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne dabar"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Tvarkyti"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Įsigykite našumo pagerinimo paslaugą."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lv/strings.xml b/packages/CarrierDefaultApp/res/values-lv/strings.xml
index 1fefe92..2fd9837 100644
--- a/packages/CarrierDefaultApp/res/values-lv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lv/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Tomēr turpināt, izmantojot pārlūkprogrammu"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Veiktspējas uzlabojums"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Uzlabojiet 5G iespējas"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s iesaka iegādāties veiktspējas uzlabošanas plānu. Pieskarieties, lai to iegādātos no %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Vēlāk"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pārvaldīt"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Iegādājieties veiktspējas uzlabojumu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mk/strings.xml b/packages/CarrierDefaultApp/res/values-mk/strings.xml
index 425edfc..6eca2b5 100644
--- a/packages/CarrierDefaultApp/res/values-mk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"На пример, страницата за најавување може да не припаѓа на прикажаната организација."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Сепак продолжи преку прелистувач"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Засилување на изведбата"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобрете го вашето доживување со 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препорачува да купите пакет за засилување на изведбата. Допрете за да купите преку %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управувајте"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете засилување на изведбата."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ml/strings.xml b/packages/CarrierDefaultApp/res/values-ml/strings.xml
index f258411..2577a144 100644
--- a/packages/CarrierDefaultApp/res/values-ml/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ml/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ഉദാഹരണത്തിന്, കാണിച്ചിരിക്കുന്ന ഓർഗനൈസേഷന്റേതായിരിക്കില്ല ലോഗിൻ പേജ്."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"എന്തായാലും ബ്രൗസർ വഴി തുടരുക"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"പ്രകടന ബൂസ്റ്റ്"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"നിങ്ങളുടെ 5G അനുഭവം മെച്ചപ്പെടുത്തുക"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"പ്രകടന ബൂസ്റ്റ് പ്ലാൻ വാങ്ങാൻ %1$s നിർദ്ദേശിക്കുന്നു. %2$s വഴി വാങ്ങാൻ ടാപ്പ് ചെയ്യുക."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ഇപ്പോൾ വേണ്ട"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"മാനേജ് ചെയ്യുക"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"പ്രകടന ബൂസ്റ്റ് വാങ്ങൂ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mn/strings.xml b/packages/CarrierDefaultApp/res/values-mn/strings.xml
index 12e1719..f0fc546 100644
--- a/packages/CarrierDefaultApp/res/values-mn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Жишээлбэл нэвтрэх хуудас нь харагдаж буй байгууллагынх биш байж болно."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ямар ч тохиолдолд хөтчөөр үргэлжлүүлэх"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Гүйцэтгэлийн идэвхжүүлэлт"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-н хэрэглээгээ сайжруулах"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s гүйцэтгэл нэмэгдүүлэх багцыг худалдаж авахыг зөвлөж байна. %2$s-р дамжуулан худалдан авах бол товшино уу."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Одоо биш"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Удирдах"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Гүйцэтгэлийн идэвхжүүлэлтийг худалдаж аваарай."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index a48c605..75cbb1b 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पृष्ठ दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"तरीही ब्राउझरद्वारे सुरू ठेवा"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफॉर्मन्स बूस्ट"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"तुमच्या 5G अनुभवामध्ये सुधारणा करा"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s हे परफॉर्मन्स बूस्ट प्लॅन खरेदी करण्याची शिफारस करते. %2$s वरून खरेदी करण्यासाठी टॅप करा."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"आता नको"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापित करा"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"परफॉर्मन्स बूस्ट खरेदी करा."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ms/strings.xml b/packages/CarrierDefaultApp/res/values-ms/strings.xml
index 85651f4..1484233 100644
--- a/packages/CarrierDefaultApp/res/values-ms/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ms/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Teruskan juga melalui penyemak imbas"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Peningkatan prestasi"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G anda"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mengesyorkan pembelian pelan peningkatan prestasi. Ketik untuk membeli melalui %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Bukan sekarang"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Urus"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli perangsang prestasi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-my/strings.xml b/packages/CarrierDefaultApp/res/values-my/strings.xml
index 34c54b9..e7a860e 100644
--- a/packages/CarrierDefaultApp/res/values-my/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-my/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ဥပမာ− ဝင်ရောက်ရန် စာမျက်နှာသည် ပြသထားသည့် အဖွဲ့အစည်းနှင့် သက်ဆိုင်မှုမရှိခြင်း ဖြစ်နိုင်ပါသည်။"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"မည်သို့ပင်ဖြစ်စေ ဘရောက်ဇာမှတစ်ဆင့် ရှေ့ဆက်ရန်"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ်"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G အသုံးပြုမှု ပိုမိုကောင်းမွန်စေခြင်း"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s သည် စွမ်းဆောင်ရည်မြှင့်တင်သော အစီအစဉ်ဝယ်ရန် အကြံပြုပါသည်။ %2$s မှတစ်ဆင့် ဝယ်ရန် တို့ပါ။"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ယခုမလုပ်ပါ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"စီမံရန်"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ် ဝယ်ယူရန်။"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nb/strings.xml b/packages/CarrierDefaultApp/res/values-nb/strings.xml
index b30e3d9..f0d0d7e 100644
--- a/packages/CarrierDefaultApp/res/values-nb/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nb/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det er for eksempel mulig at påloggingssiden ikke tilhører organisasjonen som vises."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsett likevel via nettleseren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Bedre ytelse"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-opplevelse"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler at du kjøper et abonnement for bedre ytelse. Trykk for å kjøpe via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nå"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kjøp bedre ytelse."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ne/strings.xml b/packages/CarrierDefaultApp/res/values-ne/strings.xml
index 4dccdb9..f2b0f6e 100644
--- a/packages/CarrierDefaultApp/res/values-ne/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ne/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणका लागि, लग इन पृष्ठ देखाइएको संस्थाको नहुन सक्छ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"जे भए पनि ब्राउजर मार्फत जारी राख्नुहोस्"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"पर्फर्मेन्स बुस्ट"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G प्रयोग गर्दा अझ राम्रो सुविधा पाउनुहोस्"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ले पर्फर्मेन्स बुस्ट योजना खरिद गर्न सिफारिस गर्छ। %2$s मार्फत खरिद गर्न ट्याप गर्नुहोस्।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अहिले होइन"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापन गर्नुहोस्"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"पर्फर्मेन्स बुस्ट किन्नुहोस्।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nl/strings.xml b/packages/CarrierDefaultApp/res/values-nl/strings.xml
index 6a4642c..f8ff38a 100644
--- a/packages/CarrierDefaultApp/res/values-nl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Toch doorgaan via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestatieboost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter je 5G-functionaliteit"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveelt je aan een prestatieboostabonnement te kopen. Tik om er een te kopen via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Niet nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Beheren"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop een prestatieboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-or/strings.xml b/packages/CarrierDefaultApp/res/values-or/strings.xml
index f7349f9..bbe6f25 100644
--- a/packages/CarrierDefaultApp/res/values-or/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-or/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ଉଦାହରଣସ୍ୱରୂପ, ଲଗଇନ୍ ପୃଷ୍ଠା ଦେଖାଯାଇଥିବା ସଂସ୍ଥାର ହୋଇନଥାଇପାରେ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ବ୍ରାଉଜର୍ ଜରିଆରେ ଯେମିତିବି ହେଉ ଜାରି ରଖନ୍ତୁ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ପରଫରମାନ୍ସ ବୁଷ୍ଟ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ଆପଣଙ୍କ 5G ଅନୁଭୂତିକୁ ଉନ୍ନତ କରନ୍ତୁ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ ପ୍ଲାନ କିଣିବା ପାଇଁ ସୁପାରିଶ କରେ। %2$s ମାଧ୍ୟମରେ କିଣିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ବର୍ତ୍ତମାନ ନୁହେଁ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ କିଣନ୍ତୁ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
index 540a54c..811eca9 100644
--- a/packages/CarrierDefaultApp/res/values-pa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ਉਦਾਹਰਣ ਵੱਜੋਂ, ਲੌਗ-ਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ਬ੍ਰਾਊਜ਼ਰ ਰਾਹੀਂ ਫਿਰ ਵੀ ਜਾਰੀ ਰੱਖੋ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ਆਪਣਾ 5G ਅਨੁਭਵ ਬਿਹਤਰ ਬਣਾਓ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ਵੱਲੋਂ ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਪਲਾਨ ਖਰੀਦਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। %2$s ਰਾਹੀਂ ਖਰੀਦਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ਹੁਣੇ ਨਹੀਂ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਖਰੀਦੋ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pl/strings.xml b/packages/CarrierDefaultApp/res/values-pl/strings.xml
index de957a9..3cd3297 100644
--- a/packages/CarrierDefaultApp/res/values-pl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Kontynuuj mimo to w przeglądarce"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zwiększenie wydajności"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Lepiej wykorzystaj potencjał 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"Operator %1$s zaleca zakup abonamentu o zwiększonej wydajności. Kliknij, aby kupić u operatora %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie teraz"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Zarządzaj"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kup wzmocnienie wydajności"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
index 4a144be..85f049d 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
index 56e0c2d..981cc5f 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim através do navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento do desempenho"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore a sua experiência 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar um plano de melhoria do desempenho. Toque para comprar através do %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerir"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compre um aumento do desempenho."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt/strings.xml b/packages/CarrierDefaultApp/res/values-pt/strings.xml
index 4a144be..85f049d 100644
--- a/packages/CarrierDefaultApp/res/values-pt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ro/strings.xml b/packages/CarrierDefaultApp/res/values-ro/strings.xml
index f861137..287be5a 100644
--- a/packages/CarrierDefaultApp/res/values-ro/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ro/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuă oricum prin browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performanță"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Îmbunătățește-ți experiența cu tehnologia 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomandă cumpărarea unui plan pentru îmbunătățirea performanței. Atinge pentru a cumpăra de la %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nu acum"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionează"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achiziționează un boost de performanță."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ru/strings.xml b/packages/CarrierDefaultApp/res/values-ru/strings.xml
index f0bff17..fd1328a 100644
--- a/packages/CarrierDefaultApp/res/values-ru/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ru/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Например, страница входа в аккаунт может быть фиктивной."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Продолжить в браузере"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Повышение производительности"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Сделайте работу с 5G удобнее"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"\"%1$s\" рекомендует купить тарифный план, повышающий производительность. Чтобы приобрести тариф у оператора \"%2$s\", коснитесь экрана."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сейчас"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Настроить"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Повысьте производительность сети за плату."</string>
diff --git a/packages/CarrierDefaultApp/res/values-si/strings.xml b/packages/CarrierDefaultApp/res/values-si/strings.xml
index 166af5a..a1cd21d 100644
--- a/packages/CarrierDefaultApp/res/values-si/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-si/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"උදාහරණයක් ලෙස, පුරනය වන පිටුව පෙන්වා ඇති සංවිධානයට අයිති නැති විය හැක."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"කෙසේ වුවත් බ්රවුසරය හරහා ඉදිරියට යන්න"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"කාර්ය සාධනය ඉහළ නැංවීම"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ඔබේ 5G අත්දැකීම වැඩි දියුණු කරන්න"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s කාර්ය සාධනය වැඩි කිරීමේ සැලසුමක් මිල දී ගැනීම නිර්දේශ කරයි. %2$s හරහා මිල දී ගැනීමට තට්ටු කරන්න."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"දැන් නොවේ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"කළමනාකරණය කරන්න"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"කාර්ය සාධනය ඉහළ නැංවීමක් මිල දී ගන්න."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sk/strings.xml b/packages/CarrierDefaultApp/res/values-sk/strings.xml
index a58bd06..2655065 100644
--- a/packages/CarrierDefaultApp/res/values-sk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Pokračovať pomocou prehliadača"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšenie výkonu"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Zlepšite svoje prostredie 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s odporúča zakúpiť tarifu na zvýšenie výkonnosti. Klepnutím kúpte cez %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teraz nie"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovať"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kúpte si zvýšenie výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sl/strings.xml b/packages/CarrierDefaultApp/res/values-sl/strings.xml
index 3c1fd3e..32c2659 100644
--- a/packages/CarrierDefaultApp/res/values-sl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vseeno nadaljuj v brskalniku"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ojačevalnik zmogljivosti"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Izboljšajte izkušnjo omrežja 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s priporoča nakup paketa ojačevalnika zmogljivosti. Dotaknite se za nakup prek »%2$s«."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne zdaj"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljanje"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite ojačevalnik zmogljivosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sq/strings.xml b/packages/CarrierDefaultApp/res/values-sq/strings.xml
index 618e335..f72af39 100644
--- a/packages/CarrierDefaultApp/res/values-sq/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sq/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"për shembull, faqja e identifikimit mund të mos i përkasë organizatës së shfaqur."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vazhdo gjithsesi nëpërmjet shfletuesit"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Përforcimi i performancës"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Përmirëso përvojën tënde 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekomandon blerjen e një plani të përforcimit të performancës. Trokit për të blerë nëpërmjet %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Jo tani"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Menaxho"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Bli një paketë përforcimi të performancës."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sr/strings.xml b/packages/CarrierDefaultApp/res/values-sr/strings.xml
index d28bacc..466e38c 100644
--- a/packages/CarrierDefaultApp/res/values-sr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ипак настави преко прегледача"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Побољшање учинка"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Побољшајте 5G доживљај"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоручује куповину пакета за побољшање перформанси. Додирните да бисте купили преко %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сада"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управљај"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купите побољшање учинка."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sv/strings.xml b/packages/CarrierDefaultApp/res/values-sv/strings.xml
index ac044ec..ff438b3 100644
--- a/packages/CarrierDefaultApp/res/values-sv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sv/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsätt ändå via webbläsaren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestandahöjning"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Förbättra din 5G-upplevelse"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekommenderar att du köper en prenumeration som kan höja prestandan. Tryck för att köpa via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Inte nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Hantera"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Köp en prestandahöjning."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sw/strings.xml b/packages/CarrierDefaultApp/res/values-sw/strings.xml
index 1c72f30..17bcc0f 100644
--- a/packages/CarrierDefaultApp/res/values-sw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sw/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Endelea hata hivyo kupitia kivinjari"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Kuongeza utendaji"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Boresha hali yako ya utumiaji wa 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anapendekeza ununue mpango wa kuongeza utendaji. Gusa ili ununue kupitia %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Si sasa"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Dhibiti"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Nunua programu ya kuongeza utendaji."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ta/strings.xml b/packages/CarrierDefaultApp/res/values-ta/strings.xml
index cfc46e8..3c347e1 100644
--- a/packages/CarrierDefaultApp/res/values-ta/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ta/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"எடுத்துக்காட்டாக, உள்நுழைவுப் பக்கமானது காட்டப்படும் அமைப்பிற்குச் சொந்தமானதாக இல்லாமல் இருக்கலாம்."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"பரவாயில்லை, உலாவி வழியாகத் தொடர்க"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"பெர்ஃபார்மென்ஸ் பூஸ்ட்"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"உங்கள் 5G அனுபவத்தை மேம்படுத்துங்கள்"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"செயல்திறன் மேம்பாட்டுத் திட்டத்தை வாங்க %1$s பரிந்துரைக்கிறது. %2$s மூலம் வாங்க தட்டவும்."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"இப்போது வேண்டாம்"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"நிர்வகியுங்கள்"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ஒரு பெர்ஃபார்மென்ஸ் பூஸ்ட்டைப் பர்ச்சேஸ் செய்யுங்கள்."</string>
diff --git a/packages/CarrierDefaultApp/res/values-te/strings.xml b/packages/CarrierDefaultApp/res/values-te/strings.xml
index f31291e..003df39 100644
--- a/packages/CarrierDefaultApp/res/values-te/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-te/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ఉదాహరణకు, లాగిన్ పేజీ చూపిన సంస్థకు చెందినది కాకపోవచ్చు."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ఏదేమైనా బ్రౌజర్ ద్వారా కొనసాగించండి"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"పనితీరు బూస్ట్"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"మీ 5G అనుభవాన్ని మెరుగుపరుచుకోండి"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"పనితీరును బూస్ట్ చేసే ప్లాన్ను కొనుగోలు చేయమని %1$s సిఫార్సు చేస్తున్నారు. %2$s ద్వారా కొనుగోలు చేయడానికి ట్యాప్ చేయండి."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ఇప్పుడు కాదు"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"మేనేజ్ చేయండి"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"పనితీరు బూస్ట్ను కొనుగోలు చేయండి."</string>
diff --git a/packages/CarrierDefaultApp/res/values-th/strings.xml b/packages/CarrierDefaultApp/res/values-th/strings.xml
index f20346e..16705d4 100644
--- a/packages/CarrierDefaultApp/res/values-th/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-th/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"การเพิ่มประสิทธิภาพ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ปรับปรุงประสบการณ์การใช้งาน 5G ของคุณ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s แนะนำให้ซื้อแพ็กเกจเพิ่มประสิทธิภาพ แตะเพื่อซื้อผ่าน %2$s"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ไว้ทีหลัง"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"จัดการ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ซื้อการเพิ่มประสิทธิภาพ"</string>
diff --git a/packages/CarrierDefaultApp/res/values-tl/strings.xml b/packages/CarrierDefaultApp/res/values-tl/strings.xml
index 9e8029a..28cd237 100644
--- a/packages/CarrierDefaultApp/res/values-tl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Halimbawa, maaaring hindi pag-aari ng ipinapakitang organisasyon ang page ng login."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pag-boost ng performance"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagandahin ang iyong karanasan sa 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"Inirerekomenda ng %1$s na bumili ng plan sa performance boost. I-tap para bumili sa pamamagitan ng %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Huwag muna"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pamahalaan"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Bumili ng pang-boost ng performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-tr/strings.xml b/packages/CarrierDefaultApp/res/values-tr/strings.xml
index c8fb73b..d35db1d 100644
--- a/packages/CarrierDefaultApp/res/values-tr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Yine de tarayıcıyla devam et"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artışı"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G deneyiminizi iyileştirin"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, performans artırma planı satın almanızı öneriyor. %2$s aracılığıyla satın almak için dokunun."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Şimdi değil"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Yönet"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artışı satın alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-uk/strings.xml b/packages/CarrierDefaultApp/res/values-uk/strings.xml
index 9927ea0..5d6e34a 100644
--- a/packages/CarrierDefaultApp/res/values-uk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Наприклад, сторінка входу може не належати вказаній організації."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Усе одно продовжити у веб-переглядачі"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Підвищення продуктивності"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Покращте продуктивність свого з’єднання 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рекомендує придбати тарифний план для підвищення продуктивності. Натисніть, щоб придбати через оператора %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не зараз"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Керувати"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Придбайте підвищення продуктивності."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml
index 681998b..466b6c8 100644
--- a/packages/CarrierDefaultApp/res/values-ur/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"مثال کے طور پر ہو سکتا ہے کہ لاگ ان صفحہ دکھائی گئی تنظیم سے تعلق نہ رکھتا ہو۔"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"براؤزر کے ذریعے بہرحال جاری رکھیں"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"پرفارمینس بوسٹ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"اپنے 5G تجربے کو بہتر بنائیں"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ایک پرفارمنس بوسٹ پلان کی تجویز کرتا ہے۔ %2$s استعمال کر کے خریدنے کے لیے تھپتھپائیں۔"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ابھی نہیں"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"نظم کریں"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"پرفارمینس بوسٹ خریدیں۔"</string>
diff --git a/packages/CarrierDefaultApp/res/values-uz/strings.xml b/packages/CarrierDefaultApp/res/values-uz/strings.xml
index 47006f6..82da958 100644
--- a/packages/CarrierDefaultApp/res/values-uz/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uz/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Masalan, tizimga kirish sahifasi ko‘rsatilgan tashkilotga tegishli bo‘lmasligi mumkin."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Brauzerda davom ettirish"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Unumdorlikni kuchaytirish"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G bilan ishlashni qulaylashtiring"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s unumdorlikni oshiradigan tarif rejasini xarid qilishni tavsiya etadi. %2$s orqali xarid qilish uchun bosing."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hozir emas"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Boshqarish"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Unumdorlikni kuchaytirish xizmatini xarid qiling."</string>
diff --git a/packages/CarrierDefaultApp/res/values-vi/strings.xml b/packages/CarrierDefaultApp/res/values-vi/strings.xml
index 968b6e1..225e07b 100644
--- a/packages/CarrierDefaultApp/res/values-vi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-vi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Ví dụ: trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vẫn tiếp tục qua trình duyệt"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Tăng hiệu suất"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Cải thiện trải nghiệm sử dụng 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s đề xuất bạn mua gói tăng cường hiệu suất. Nhấn để mua thông qua %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Để sau"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Quản lý"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Mua gói tăng hiệu suất."</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
index 563117f..5be55bc 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登录页面可能并不属于页面上显示的单位。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍然通过浏览器继续操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"性能提升方案"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 体验"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s建议购买性能提升计划。点按即可通过%2$s进行购买。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"以后再说"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"购买一份性能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
index 7ed0c3c..92f53d3 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登入頁面可能並不屬於所顯示的機構。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升服務"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升服務計劃。輕按即可透過「%2$s」購買。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升服務。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
index 332ab9c..6cb4b94 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升方案"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升方案,輕觸即可透過「%2$s」購買。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zu/strings.xml b/packages/CarrierDefaultApp/res/values-zu/strings.xml
index ae84695..f8bc50c 100644
--- a/packages/CarrierDefaultApp/res/values-zu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Qhubeka noma kunjalo ngesiphequluli"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"I-boost yokusebenza"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Thuthukisa umuzwa wakho we-5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"I-%1$s incoma ukuthenga uhlelo lokuthuthukisa ukusebenza. Thepha ukuze uthenge nge-%2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hhayi manje"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Phatha"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Thenga i-boost yokusebenza."</string>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index 720e46d..e91d35b 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -19,7 +19,7 @@
<!-- Notification title text for the performance boost notification. -->
<string name="performance_boost_notification_title">Improve your app experience</string>
<!-- Notification detail text for the performance boost notification. -->
- <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more.</string>
+ <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more</string>
<!-- Notification button text to cancel the performance boost notification. -->
<string name="performance_boost_notification_button_not_now">Not now</string>
<!-- Notification button text to manage the performance boost notification. -->
diff --git a/packages/CredentialManager/Android.bp b/packages/CredentialManager/Android.bp
index 00d42bd..28b9bc0 100644
--- a/packages/CredentialManager/Android.bp
+++ b/packages/CredentialManager/Android.bp
@@ -20,6 +20,7 @@
},
static_libs: [
+ "PlatformComposeCore",
"androidx.activity_activity-compose",
"androidx.appcompat_appcompat",
"androidx.compose.animation_animation-core",
diff --git a/packages/CredentialManager/res/drawable/ic_other_devices.xml b/packages/CredentialManager/res/drawable/ic_other_devices.xml
deleted file mode 100644
index 754648c..0000000
--- a/packages/CredentialManager/res/drawable/ic_other_devices.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:ignore="VectorPath"
- android:name="vector"
- android:width="20dp"
- android:height="20dp"
- android:viewportWidth="20"
- android:viewportHeight="20">
- <path
- android:name="path"
- android:pathData="M 7.6 4.72 L 7.6 7.6 L 4.72 7.6 L 4.72 4.72 L 7.6 4.72 Z M 9.04 3.28 L 3.28 3.28 L 3.28 9.04 L 9.04 9.04 L 9.04 3.28 Z M 7.6 12.4 L 7.6 15.28 L 4.72 15.28 L 4.72 12.4 L 7.6 12.4 Z M 9.04 10.96 L 3.28 10.96 L 3.28 16.72 L 9.04 16.72 L 9.04 10.96 Z M 15.28 4.72 L 15.28 7.6 L 12.4 7.6 L 12.4 4.72 L 15.28 4.72 Z M 16.72 3.28 L 10.96 3.28 L 10.96 9.04 L 16.72 9.04 L 16.72 3.28 Z M 10.96 10.96 L 12.4 10.96 L 12.4 12.4 L 10.96 12.4 L 10.96 10.96 Z M 12.4 12.4 L 13.84 12.4 L 13.84 13.84 L 12.4 13.84 L 12.4 12.4 Z M 13.84 10.96 L 15.28 10.96 L 15.28 12.4 L 13.84 12.4 L 13.84 10.96 Z M 10.96 13.84 L 12.4 13.84 L 12.4 15.28 L 10.96 15.28 L 10.96 13.84 Z M 12.4 15.28 L 13.84 15.28 L 13.84 16.72 L 12.4 16.72 L 12.4 15.28 Z M 13.84 13.84 L 15.28 13.84 L 15.28 15.28 L 13.84 15.28 L 13.84 13.84 Z M 15.28 12.4 L 16.72 12.4 L 16.72 13.84 L 15.28 13.84 L 15.28 12.4 Z M 15.28 15.28 L 16.72 15.28 L 16.72 16.72 L 15.28 16.72 L 15.28 15.28 Z M 19.6 5.2 L 17.68 5.2 L 17.68 2.32 L 14.8 2.32 L 14.8 0.4 L 19.6 0.4 L 19.6 5.2 Z M 19.6 19.6 L 19.6 14.8 L 17.68 14.8 L 17.68 17.68 L 14.8 17.68 L 14.8 19.6 L 19.6 19.6 Z M 0.4 19.6 L 5.2 19.6 L 5.2 17.68 L 2.32 17.68 L 2.32 14.8 L 0.4 14.8 L 0.4 19.6 Z M 0.4 0.4 L 0.4 5.2 L 2.32 5.2 L 2.32 2.32 L 5.2 2.32 L 5.2 0.4 L 0.4 0.4 Z"
- android:fillColor="#000000"
- android:strokeWidth="1"/>
-</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_other_sign_in.xml b/packages/CredentialManager/res/drawable/ic_other_sign_in.xml
deleted file mode 100644
index 8150197..0000000
--- a/packages/CredentialManager/res/drawable/ic_other_sign_in.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
- ~ Copyright (C) 2022 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.
- -->
-
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:ignore="VectorPath"
- android:name="vector"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:name="path"
- android:pathData="M 20 19 L 12 19 L 12 21 L 20 21 C 21.1 21 22 20.1 22 19 L 22 5 C 22 3.9 21.1 3 20 3 L 12 3 L 12 5 L 20 5 L 20 19 Z"
- android:fillColor="#000"
- android:strokeWidth="1"/>
- <path
- android:name="path_1"
- android:pathData="M 12 7 L 10.6 8.4 L 13.2 11 L 8.85 11 C 8.42 9.55 7.09 8.5 5.5 8.5 C 3.57 8.5 2 10.07 2 12 C 2 13.93 3.57 15.5 5.5 15.5 C 7.09 15.5 8.42 14.45 8.85 13 L 13.2 13 L 10.6 15.6 L 12 17 L 17 12 L 12 7 Z M 5.5 13.5 C 4.67 13.5 4 12.83 4 12 C 4 11.17 4.67 10.5 5.5 10.5 C 6.33 10.5 7 11.17 7 12 C 7 12.83 6.33 13.5 5.5 13.5 Z"
- android:fillColor="#000"
- android:strokeWidth="1"/>
-</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml b/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml
new file mode 100644
index 0000000..ce2aeb2
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<vector
+ android:alpha="0.8"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+>
+<group>
+ <clip-path android:pathData="M0,0h24v24h-24z"/>
+ <path android:fillColor="#444746" android:pathData="M20,19H12V21H20C21.1,21 22,20.1 22,19V5C22,3.9 21.1,3 20,3H12V5H20V19Z"/>
+ <path android:fillColor="#444746" android:pathData="M12,7L10.6,8.4L13.2,11H8.85C8.42,9.55 7.09,8.5 5.5,8.5C3.57,8.5 2,10.07 2,12C2,13.93 3.57,15.5 5.5,15.5C7.09,15.5 8.42,14.45 8.85,13H13.2L10.6,15.6L12,17L17,12L12,7ZM5.5,13.5C4.67,13.5 4,12.83 4,12C4,11.17 4.67,10.5 5.5,10.5C6.33,10.5 7,11.17 7,12C7,12.83 6.33,13.5 5.5,13.5Z"/>
+</group>
+</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_passkey.xml b/packages/CredentialManager/res/drawable/ic_passkey.xml
deleted file mode 100644
index 041a321..0000000
--- a/packages/CredentialManager/res/drawable/ic_passkey.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="28dp"
- android:height="24dp"
- android:viewportWidth="28"
- android:viewportHeight="24">
- <path
- android:pathData="M27.453,13.253C27.453,14.952 26.424,16.411 24.955,17.041L26.21,18.295L24.839,19.666L26.21,21.037L23.305,23.942L22.012,22.65L22.012,17.156C20.385,16.605 19.213,15.066 19.213,13.253C19.213,10.977 21.058,9.133 23.333,9.133C25.609,9.133 27.453,10.977 27.453,13.253ZM25.47,13.254C25.47,14.434 24.514,15.39 23.334,15.39C22.154,15.39 21.197,14.434 21.197,13.254C21.197,12.074 22.154,11.118 23.334,11.118C24.514,11.118 25.47,12.074 25.47,13.254Z"
- android:fillColor="#00639B"
- android:fillType="evenOdd"/>
- <path
- android:pathData="M17.85,5.768C17.85,8.953 15.268,11.536 12.083,11.536C8.897,11.536 6.315,8.953 6.315,5.768C6.315,2.582 8.897,0 12.083,0C15.268,0 17.85,2.582 17.85,5.768Z"
- android:fillColor="#00639B"/>
- <path
- android:pathData="M0.547,20.15C0.547,16.32 8.23,14.382 12.083,14.382C13.59,14.382 15.684,14.679 17.674,15.269C18.116,16.454 18.952,17.447 20.022,18.089V23.071H0.547V20.15Z"
- android:fillColor="#00639B"/>
-</vector>
diff --git a/packages/CredentialManager/res/drawable/ic_passkey_24.xml b/packages/CredentialManager/res/drawable/ic_passkey_24.xml
new file mode 100644
index 0000000..a2c4f37
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_passkey_24.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<vector
+ android:alpha="0.8"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+ <path android:fillColor="#4C463C" android:fillType="evenOdd" android:pathData="M22.18,14.09C22.18,15.364 21.408,16.459 20.306,16.931L21.247,17.872L20.219,18.9L21.247,19.928L19.068,22.107L18.099,21.138L18.099,17.017C16.878,16.604 16,15.45 16,14.09C16,12.383 17.383,11 19.09,11C20.796,11 22.18,12.383 22.18,14.09ZM20.692,14.091C20.692,14.976 19.975,15.693 19.09,15.693C18.205,15.693 17.488,14.976 17.488,14.091C17.488,13.206 18.205,12.488 19.09,12.488C19.975,12.488 20.692,13.206 20.692,14.091Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M14.978,8.476C14.978,10.865 13.041,12.802 10.652,12.802C8.263,12.802 6.326,10.865 6.326,8.476C6.326,6.087 8.263,4.15 10.652,4.15C13.041,4.15 14.978,6.087 14.978,8.476Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M2,19.263C2,16.39 7.762,14.937 10.652,14.937C11.782,14.937 13.353,15.16 14.845,15.602C15.177,16.491 15.804,17.236 16.607,17.717V21.454H2V19.263Z"/>
+</vector>
diff --git a/packages/CredentialManager/res/drawable/ic_password.xml b/packages/CredentialManager/res/drawable/ic_password.xml
deleted file mode 100644
index bf3056a..0000000
--- a/packages/CredentialManager/res/drawable/ic_password.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
- ~ Copyright (C) 2022 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.
- -->
-
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:ignore="VectorPath"
- android:name="vector"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:name="path"
- android:pathData="M 8.71 10.29 C 8.52 10.1 8.28 10 8 10 L 7.75 10 L 7.75 8.75 C 7.75 7.98 7.48 7.33 6.95 6.8 C 6.42 6.27 5.77 6 5 6 C 4.23 6 3.58 6.27 3.05 6.8 C 2.52 7.33 2.25 7.98 2.25 8.75 L 2.25 10 L 2 10 C 1.72 10 1.48 10.1 1.29 10.29 C 1.1 10.48 1 10.72 1 11 L 1 16 C 1 16.28 1.1 16.52 1.29 16.71 C 1.48 16.9 1.72 17 2 17 L 8 17 C 8.28 17 8.52 16.9 8.71 16.71 C 8.9 16.52 9 16.28 9 16 L 9 11 C 9 10.72 8.9 10.48 8.71 10.29 Z M 6.25 10 L 3.75 10 L 3.75 8.75 C 3.75 8.4 3.87 8.1 4.11 7.86 C 4.35 7.62 4.65 7.5 5 7.5 C 5.35 7.5 5.65 7.62 5.89 7.86 C 6.13 8.1 6.25 8.4 6.25 8.75 L 6.25 10 Z M 10 14 L 23 14 L 23 16 L 10 16 Z M 21.5 9 C 21.102 9 20.721 9.158 20.439 9.439 C 20.158 9.721 20 10.102 20 10.5 C 20 10.898 20.158 11.279 20.439 11.561 C 20.721 11.842 21.102 12 21.5 12 C 21.898 12 22.279 11.842 22.561 11.561 C 22.842 11.279 23 10.898 23 10.5 C 23 10.102 22.842 9.721 22.561 9.439 C 22.279 9.158 21.898 9 21.5 9 Z M 16.5 9 C 16.102 9 15.721 9.158 15.439 9.439 C 15.158 9.721 15 10.102 15 10.5 C 15 10.898 15.158 11.279 15.439 11.561 C 15.721 11.842 16.102 12 16.5 12 C 16.898 12 17.279 11.842 17.561 11.561 C 17.842 11.279 18 10.898 18 10.5 C 18 10.102 17.842 9.721 17.561 9.439 C 17.279 9.158 16.898 9 16.5 9 Z M 11.5 9 C 11.102 9 10.721 9.158 10.439 9.439 C 10.158 9.721 10 10.102 10 10.5 C 10 10.898 10.158 11.279 10.439 11.561 C 10.721 11.842 11.102 12 11.5 12 C 11.898 12 12.279 11.842 12.561 11.561 C 12.842 11.279 13 10.898 13 10.5 C 13 10.102 12.842 9.721 12.561 9.439 C 12.279 9.158 11.898 9 11.5 9 Z"
- android:fillColor="#000"
- android:strokeWidth="1"/>
-</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_password_24.xml b/packages/CredentialManager/res/drawable/ic_password_24.xml
new file mode 100644
index 0000000..8b24e88
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_password_24.xml
@@ -0,0 +1,34 @@
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:ignore="VectorPath"
+ android:name="vector"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <group>
+ <clip-path android:pathData="M0,0h24v24h-24z"/>
+ <path android:fillColor="#4C463C" android:pathData="M8.46,10.29C8.27,10.1 8.03,10 7.75,10H7.5V8.75C7.5,7.98 7.23,7.33 6.7,6.8C6.17,6.27 5.52,6 4.75,6C3.98,6 3.33,6.27 2.8,6.8C2.27,7.33 2,7.98 2,8.75V10H1.75C1.47,10 1.23,10.1 1.04,10.29C0.85,10.48 0.75,10.72 0.75,11V16C0.75,16.28 0.85,16.52 1.04,16.71C1.23,16.9 1.47,17 1.75,17H7.75C8.03,17 8.27,16.9 8.46,16.71C8.65,16.52 8.75,16.28 8.75,16V11C8.75,10.72 8.65,10.48 8.46,10.29ZM6,10H3.5V8.75C3.5,8.4 3.62,8.1 3.86,7.86C4.1,7.62 4.4,7.5 4.75,7.5C5.1,7.5 5.4,7.62 5.64,7.86C5.88,8.1 6,8.4 6,8.75V10Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M23.5,14H10.5V16H23.5V14Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M22,12C22.828,12 23.5,11.328 23.5,10.5C23.5,9.672 22.828,9 22,9C21.172,9 20.5,9.672 20.5,10.5C20.5,11.328 21.172,12 22,12Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M17,12C17.828,12 18.5,11.328 18.5,10.5C18.5,9.672 17.828,9 17,9C16.172,9 15.5,9.672 15.5,10.5C15.5,11.328 16.172,12 17,12Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M12,12C12.828,12 13.5,11.328 13.5,10.5C13.5,9.672 12.828,9 12,9C11.172,9 10.5,9.672 10.5,10.5C10.5,11.328 11.172,12 12,12Z"/>
+ </group>
+</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml
index 3d32642..f0f040f 100644
--- a/packages/CredentialManager/res/values-af/strings.xml
+++ b/packages/CredentialManager/res/values-af/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Maak sigblad toe"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gaan terug na die vorige bladsy"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Maak toe"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gebruik jou gestoorde wagwoordsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gebruik jou gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Kies ’n gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index 76533e5..730b0b0 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"ሌሎች የይለፍ ቃል አስተዳዳሪዎች"</string>
<string name="close_sheet" msgid="1393792015338908262">"ሉህን ዝጋ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ወደ ቀዳሚው ገፅ ይመለሱ"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ዝጋ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"የተቀመጠ የይለፍ ቁልፍዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"የተቀመጠ መግቢያዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"የተቆለፉ የሚስጥር ቁልፍ አስተዳዳሪዎች"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ለመክፈት መታ ያድርጉ"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ምንም የመግቢያ ማስረጃ የለም"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ውስጥ ምንም የመግቢያ መረጃ የለም"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"መግቢያዎችን ያስተዳድሩ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ከሌላ መሣሪያ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"የተለየ መሣሪያ ይጠቀሙ"</string>
diff --git a/packages/CredentialManager/res/values-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml
index c5de5c8..666f903 100644
--- a/packages/CredentialManager/res/values-ar/strings.xml
+++ b/packages/CredentialManager/res/values-ar/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"خدمات مدراء كلمات المرور الأخرى"</string>
<string name="close_sheet" msgid="1393792015338908262">"إغلاق ورقة البيانات"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"العودة إلى الصفحة السابقة"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"إغلاق"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"هل تريد استخدام مفتاح المرور المحفوظ لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"هل تريد استخدام بيانات اعتماد تسجيل الدخول المحفوظة لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"خدمات إدارة كلمات المرور المقفولة"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"انقر لفتح القفل."</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ما مِن معلومات تسجيل دخول."</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"ليس هناك معلومات تسجيل دخول في <xliff:g id="SOURCE">%1$s</xliff:g>."</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"إداراة عمليات تسجيل الدخول"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"من جهاز آخر"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استخدام جهاز مختلف"</string>
diff --git a/packages/CredentialManager/res/values-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml
index 1ee0a46..6202de5 100644
--- a/packages/CredentialManager/res/values-as/strings.xml
+++ b/packages/CredentialManager/res/values-as/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"শ্বীট বন্ধ কৰক"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"পূৰ্বৱৰ্তী পৃষ্ঠালৈ ঘূৰি যাওক"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ কৰক"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা পাছকী ব্যৱহাৰ কৰিবনে?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা ছাইন ইন তথ্য ব্যৱহাৰ কৰিবনে?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ হৈ থকা এটা ছাইন ইন বাছনি কৰক"</string>
diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index 778b78f..2481a5c 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Səhifəni bağlayın"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Əvvəlki səhifəyə qayıdın"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Bağlayın"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış giriş açarı istifadə edilsin?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişdən istifadə edilsin?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişi seçin"</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index e18aed5..1e7e92e 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Drugi menadžeri lozinki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zatvorite tabelu"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvorite"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite da koristite sačuvani pristupni kôd za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite da koristite sačuvane podatke za prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menadžeri zaključanih lozinki"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da biste otključali"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavljivanje"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka za prijavljivanje u: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavljivanjima"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Sa drugog uređaja"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Koristi drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml
index d3512ba..f89454a 100644
--- a/packages/CredentialManager/res/values-be/strings.xml
+++ b/packages/CredentialManager/res/values-be/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Іншыя спосабы ўваходу"</string>
<string name="close_sheet" msgid="1393792015338908262">"Закрыць аркуш"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вярнуцца да папярэдняй старонкі"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыць"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Скарыстаць захаваны ключ доступу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Скарыстаць захаваныя спосабы ўваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблакіраваныя спосабы ўваходу"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Націсніце, каб разблакіраваць"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма даных для ўваходу"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ва ўліковым запісе <xliff:g id="SOURCE">%1$s</xliff:g> адсутнічае інфармацыя для ўваходу"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіраваць спосабамі ўваходу"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншай прылады"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Скарыстаць іншую прыладу"</string>
diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index 35926ca..530c823 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Други мениджъри на пароли"</string>
<string name="close_sheet" msgid="1393792015338908262">"Затваряне на таблицата"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Назад към предишната страница"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Затваряне"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се използва ли запазеният ви код за достъп за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се използват ли запазените ви данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заключени мениджъри на пароли"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Докоснете, за да отключите"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма данни за вход"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> не съдържа данни за вход"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление на данните за вход"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"От друго устройство"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Използване на друго устройство"</string>
diff --git a/packages/CredentialManager/res/values-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml
index 3273aa4..c3f0e4b 100644
--- a/packages/CredentialManager/res/values-bn/strings.xml
+++ b/packages/CredentialManager/res/values-bn/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"অন্যান্য Password Manager"</string>
<string name="close_sheet" msgid="1393792015338908262">"শিট বন্ধ করুন"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"আগের পৃষ্ঠায় ফিরে যান"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ করুন"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা পাসকী ব্যবহার করবেন?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা সাইন-ইন সম্পর্কিত ক্রেডেনশিয়াল ব্যবহার করবেন?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"লক করা Password Manager"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"আনলক করতে ট্যাপ করুন"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"সাইন-ইন সম্পর্কিত তথ্য নেই"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-এ সাইন-ইন সম্পর্কিত কোনও তথ্য নেই"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"সাইন-ইন করার ক্রেডেনশিয়াল ম্যানেজ করুন"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"অন্য ডিভাইস থেকে"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"আলাদা ডিভাইস ব্যবহার করুন"</string>
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index 2751651..d980614 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji lozinki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zatvaranje tabele"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Povratak na prethodnu stranicu"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvaranje"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Koristiti sačuvani pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Koristiti sačuvanu prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zaključani upravitelji lozinki"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da otključate"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavu"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema informacija za prijavu na <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavama"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"S drugog uređaja"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 0d115d5..afbfe50 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Altres gestors de contrasenyes"</string>
<string name="close_sheet" msgid="1393792015338908262">"Tanca el full"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna a la pàgina anterior"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Tanca"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vols utilitzar la clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vols utilitzar l\'inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestors de contrasenyes bloquejats"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca per desbloquejar"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sense informació d\'inici de sessió"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Sense informació d\'inici de sessió per a <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestiona els inicis de sessió"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Des d\'un altre dispositiu"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utilitza un dispositiu diferent"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index f3e290b..72e5525 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Další správci hesel"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zavřít list"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zpět na předchozí stránku"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zavřít"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Použít uložený přístupový klíč pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Použít uložené přihlášení pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Uzamčení správci hesel"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Klepnutím odemknete"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žádné informace o přihlášení"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> neobsahuje žádné přihlašovací údaje"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovat přihlášení"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z jiného zařízení"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použít jiné zařízení"</string>
diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml
index 76c8a81..148bba8 100644
--- a/packages/CredentialManager/res/values-da/strings.xml
+++ b/packages/CredentialManager/res/values-da/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Andre adgangskodeadministratorer"</string>
<string name="close_sheet" msgid="1393792015338908262">"Luk arket"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbage til den forrige side"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Luk"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruge din gemte adgangsnøgle til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruge din gemte loginmetode til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste adgangskodeadministratorer"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryk for at låse op"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen loginoplysninger"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Der er ingen loginoplysninger i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer loginmetoder"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en anden enhed"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Brug en anden enhed"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index adcaae4..103a3d2 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -49,6 +49,8 @@
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zurück zur vorherigen Seite"</string>
<!-- no translation found for accessibility_close_button (1163435587545377687) -->
<skip />
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index df1b1a7..8cb3f28 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Κλείσιμο φύλλου"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Επιστροφή στην προηγούμενη σελίδα"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Κλείσιμο"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Να χρησιμοποιηθεί το αποθηκευμένο κλειδί πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Να χρησιμοποιηθούν τα αποθηκευμένα στοιχεία σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Επιλογή αποθηκευμένων στοιχείων σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml
index e350449c..ffba3ce 100644
--- a/packages/CredentialManager/res/values-en-rAU/strings.xml
+++ b/packages/CredentialManager/res/values-en-rAU/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index f6ab350..32bbe44 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml
index e350449c..ffba3ce 100644
--- a/packages/CredentialManager/res/values-en-rGB/strings.xml
+++ b/packages/CredentialManager/res/values-en-rGB/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml
index e350449c..ffba3ce 100644
--- a/packages/CredentialManager/res/values-en-rIN/strings.xml
+++ b/packages/CredentialManager/res/values-en-rIN/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index 7f5f0c1..49db2fc 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml
index d700ed6..91afadc 100644
--- a/packages/CredentialManager/res/values-es-rUS/strings.xml
+++ b/packages/CredentialManager/res/values-es-rUS/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Otros administradores de contraseñas"</string>
<string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Quieres usar tu llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Quieres usar tu acceso guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Administradores de contraseñas bloqueados"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Presiona para desbloquear"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de acceso"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de acceso en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrar accesos"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Desde otro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otra voz"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index ee056af..b1ff414 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Otros gestores de contraseñas"</string>
<string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Usar la llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Usar el inicio de sesión guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestores de contraseñas bloqueados"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocar para desbloquear"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de inicio de sesión"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de inicio de sesión en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionar inicios de sesión"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De otro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml
index accdea5..5bacae3 100644
--- a/packages/CredentialManager/res/values-et/strings.xml
+++ b/packages/CredentialManager/res/values-et/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Muud paroolihaldurid"</string>
<string name="close_sheet" msgid="1393792015338908262">"Sule leht"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Minge tagasi eelmisele lehele"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Sule"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud pääsuvõtit?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud sisselogimisandmeid?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukustatud paroolihaldurid"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avamiseks puudutage"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sisselogimisteave puudub"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontol <xliff:g id="SOURCE">%1$s</xliff:g> puudub sisselogimisteave"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Sisselogimisandmete haldamine"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Muus seadmes"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Kasuta teist seadet"</string>
diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml
index 18d6532..9052bd2 100644
--- a/packages/CredentialManager/res/values-eu/strings.xml
+++ b/packages/CredentialManager/res/values-eu/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Beste pasahitz-kudeatzaile batzuk"</string>
<string name="close_sheet" msgid="1393792015338908262">"Itxi orria"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Itzuli aurreko orrira"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Itxi"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde duzun sarbide-gakoa erabili nahi duzu?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde dituzun kredentzialak erabili nahi dituzu?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Blokeatutako pasahitz-kudeatzaileak"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Desblokeatzeko, sakatu hau"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ez dago saioa hasteko informaziorik"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ez dago saioa hasteko informaziorik <xliff:g id="SOURCE">%1$s</xliff:g> kontuan"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kudeatu kredentzialak"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Beste gailu batean gordetakoak"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Erabili beste gailu bat"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index 68ec685..9e01bf0 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"دیگر مدیران گذرواژه"</string>
<string name="close_sheet" msgid="1393792015338908262">"بستن برگ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"برگشتن به صفحه قبلی"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"بستن"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"گذرکلید ذخیرهشده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ورود به سیستم ذخیرهشده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مدیران گذرواژه قفلشده"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"برای باز کردن قفل ضربه بزنید"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"اطلاعات ورود به سیستم موجود نیست"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"هیچ اطلاعات ورود به سیستمی در <xliff:g id="SOURCE">%1$s</xliff:g> وجود ندارد"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"مدیریت ورود به سیستمها"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"از دستگاهی دیگر"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استفاده از دستگاه دیگری"</string>
diff --git a/packages/CredentialManager/res/values-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml
index 266a2a9..268dbca 100644
--- a/packages/CredentialManager/res/values-fi/strings.xml
+++ b/packages/CredentialManager/res/values-fi/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Muut salasanojen ylläpitotyökalut"</string>
<string name="close_sheet" msgid="1393792015338908262">"Sulje taulukko"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Takaisin edelliselle sivulle"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Sulje"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Käytetäänkö tallennettua avainkoodiasi täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Käytetäänkö tallennettuja kirjautumistietoja täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukitut salasanojen ylläpitotyökalut"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avaa napauttamalla"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ei kirjautumistietoja"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ei kirjautumistietoja (<xliff:g id="SOURCE">%1$s</xliff:g>)"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Muuta kirjautumistietoja"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Toiselta laitteelta"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Käytä toista laitetta"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index 914ee55..d5fd858 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -49,6 +49,8 @@
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Retourner à la page précédente"</string>
<!-- no translation found for accessibility_close_button (1163435587545377687) -->
<skip />
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser votre connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choisir une connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index faca62d..95917e1 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Autres gestionnaires de mots de passe"</string>
<string name="close_sheet" msgid="1393792015338908262">"Fermer la feuille"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revenir à la page précédente"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Fermer"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser vos informations de connexion enregistrées pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestionnaires de mots de passe verrouillés"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Appuyer pour déverrouiller"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Aucune information de connexion"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Aucune info de connexion dans <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gérer les connexions"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Depuis un autre appareil"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utiliser un autre appareil"</string>
diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml
index 3b2d6f6..88dc4a0 100644
--- a/packages/CredentialManager/res/values-gl/strings.xml
+++ b/packages/CredentialManager/res/values-gl/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Outros xestores de contrasinais"</string>
<string name="close_sheet" msgid="1393792015338908262">"Pechar folla"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver á páxina anterior"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Pechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Queres usar a clave de acceso gardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Queres usar o método de inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Xestores de contrasinais bloqueados"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca para desbloquear"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sen información de inicio de sesión"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non hai información de inicio de sesión para <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Xestionar os métodos de inicio de sesión"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Doutro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar outro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml
index d3339b7..1237483 100644
--- a/packages/CredentialManager/res/values-gu/strings.xml
+++ b/packages/CredentialManager/res/values-gu/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"અન્ય પાસવર્ડ મેનેજર"</string>
<string name="close_sheet" msgid="1393792015338908262">"શીટ બંધ કરો"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"પાછલા પેજ પર પરત જાઓ"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"બંધ કરો"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારી સાચવેલી પાસકીનો ઉપયોગ કરીએ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારા સાચવેલા સાઇન-ઇનનો ઉપયોગ કરીએ?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"લૉક કરેલા પાસવર્ડ મેનેજર"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"અનલૉક કરવા માટે ટૅપ કરો"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"સાઇન-ઇનની કોઈ માહિતી નથી"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>માં સાઇન-ઇનની કોઈ માહિતી નથી"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"સાઇન-ઇન મેનેજ કરો"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"કોઈ અન્ય ડિવાઇસમાંથી"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"કોઈ અન્ય ડિવાઇસનો ઉપયોગ કરો"</string>
diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index f2790f4..7f3bb49 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"दूसरे पासवर्ड मैनेजर"</string>
<string name="close_sheet" msgid="1393792015338908262">"शीट बंद करें"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"पिछले पेज पर वापस जाएं"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करें"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई पासकी का इस्तेमाल करना है?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई जानकारी का इस्तेमाल करना है?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक किए गए पासवर्ड मैनेजर"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करने के लिए टैप करें"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन करने से जुड़ी कोई जानकारी उपलब्ध नहीं है"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> में साइन-इन की जानकारी नहीं है"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इन करने की सुविधा को मैनेज करें"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"किसी दूसरे डिवाइस से"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"दूसरे डिवाइस का इस्तेमाल करें"</string>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 3d813f9..7a8354a 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji zaporki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zatvaranje lista"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvori"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite li upotrijebiti spremljeni pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite li upotrijebiti spremljene podatke za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Upravitelji zaključanih zaporki"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite za otključavanje"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka o prijavi"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka o prijavi u aplikaciji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljanje prijavama"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na drugom uređaju"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml
index e3b0fec..ae136be 100644
--- a/packages/CredentialManager/res/values-hu/strings.xml
+++ b/packages/CredentialManager/res/values-hu/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Egyéb jelszókezelők"</string>
<string name="close_sheet" msgid="1393792015338908262">"Munkalap bezárása"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vissza az előző oldalra"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Bezárás"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett azonosítókulcsot használni?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett bejelentkezési adatait használni?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zárolt jelszókezelők"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Koppintson a feloldáshoz"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nincsenek bejelentkezési adatok"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nem találhatók bejelentkezési adatok itt: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Bejelentkezési adatok kezelése"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Másik eszközről"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Másik eszköz használata"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index 6cdc76f..6b7c973 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Գաղտնաբառերի այլ կառավարիչներ"</string>
<string name="close_sheet" msgid="1393792015338908262">"Փակել թերթը"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Անցնել նախորդ էջ"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Փակել"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Օգտագործե՞լ պահված անցաբառը <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Օգտագործե՞լ մուտքի պահված տվյալները <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Գաղտնաբառերի կողպված կառավարիչներ"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Հպեք ապակողպելու համար"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Մուտքի տվյալներ չկան"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Մուտքի տվյալներ չկան այստեղ՝ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Մուտքի կառավարում"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Մեկ այլ սարքից"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Օգտագործել այլ սարք"</string>
diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index f0f0089..9eb3c65 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Pengelola sandi lainnya"</string>
<string name="close_sheet" msgid="1393792015338908262">"Tutup sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan info login tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Pengelola sandi terkunci"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ketuk untuk membuka kunci"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Tidak ada info login"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Tidak ada info login di <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kelola login"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Dari perangkat lain"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gunakan perangkat lain"</string>
diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml
index 7ee8b5d..b627058 100644
--- a/packages/CredentialManager/res/values-is/strings.xml
+++ b/packages/CredentialManager/res/values-is/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Önnur aðgangsorðastjórnun"</string>
<string name="close_sheet" msgid="1393792015338908262">"Loka blaði"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Fara aftur á fyrri síðu"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Loka"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Notað vistaðan aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Nota vistaða innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Læst aðgangsorðastjórnun"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ýttu til að opna"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Engar innskráningarupplýsingar"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Engar innskráningarupplýsingar á <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Stjórna innskráningu"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Úr öðru tæki"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Nota annað tæki"</string>
diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml
index 7f39c1d..9497cea 100644
--- a/packages/CredentialManager/res/values-it/strings.xml
+++ b/packages/CredentialManager/res/values-it/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Altri gestori delle password"</string>
<string name="close_sheet" msgid="1393792015338908262">"Chiudi il foglio"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna alla pagina precedente"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Chiudi"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vuoi usare la passkey salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vuoi usare l\'accesso salvato per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestori delle password bloccati"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocca per sbloccare"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nessuna informazione di accesso"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non sono presenti dati di accesso in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestisci gli accessi"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Da un altro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usa un dispositivo diverso"</string>
diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml
index 9100b51..9197ac6 100644
--- a/packages/CredentialManager/res/values-iw/strings.xml
+++ b/packages/CredentialManager/res/values-iw/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"מנהלי סיסמאות אחרים"</string>
<string name="close_sheet" msgid="1393792015338908262">"סגירת הגיליון"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"חזרה לדף הקודם"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"סגירה"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"להשתמש במפתח גישה שנשמר עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"להשתמש בפרטי הכניסה שנשמרו עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"מנהלי סיסמאות נעולים"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"יש להקיש כדי לבטל את הנעילה"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"אין פרטי כניסה"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"אין פרטי כניסה ב-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ניהול כניסות"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ממכשיר אחר"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"צריך להשתמש במכשיר אחר"</string>
diff --git a/packages/CredentialManager/res/values-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml
index c49dd39..3c97777 100644
--- a/packages/CredentialManager/res/values-ja/strings.xml
+++ b/packages/CredentialManager/res/values-ja/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"シートを閉じます"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"前のページに戻ります"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"閉じる"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したパスキーを使用しますか?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報を使用しますか?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報の選択"</string>
diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index f5eb7c9..4d0d9f7 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"ფურცლის დახურვა"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"წინა გვერდზე დაბრუნება"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"დახურვა"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"გსურთ თქვენი დამახსოვრებული წვდომის გასაღების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"გსურთ თქვენი დამახსოვრებული სისტემაში შესვლის მონაცემების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"აირჩიეთ სისტემაში შესვლის ინფორმაცია აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 8864cb4..4be32d8 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Басқа құпия сөз менеджерлері"</string>
<string name="close_sheet" msgid="1393792015338908262">"Парақты жабу"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Алдыңғы бетке оралу"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Жабу"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру кілті пайдаланылсын ба?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректері пайдаланылсын ба?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Құлыпталған құпия сөз менеджерлері"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Құлыпты ашу үшін түртіңіз."</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Кіру ақпараты жоқ."</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтында кіру туралы ешқандай ақпарат жоқ."</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіру әрекеттерін басқару"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Басқа құрылғыдан жасау"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Басқа құрылғыны пайдалану"</string>
diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index f257789..313c0c5 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"បិទសន្លឹក"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ត្រឡប់ទៅទំព័រមុនវិញ"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"បិទ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ប្រើកូដសម្ងាត់ដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ប្រើការចូលគណនីដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ជ្រើសរើសការចូលគណនីដែលបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index c41bd63..750c51b 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"ಶೀಟ್ ಮುಚ್ಚಿರಿ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ಹಿಂದಿನ ಪುಟಕ್ಕೆ ಹಿಂದಿರುಗಿ"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"ಮುಚ್ಚಿರಿ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಪಾಸ್ಕೀ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಸೈನ್-ಇನ್ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ಸೈನ್-ಇನ್ ಮಾಹಿತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 20b734a..89b5a3f 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"기타 비밀번호 관리자"</string>
<string name="close_sheet" msgid="1393792015338908262">"시트 닫기"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"이전 페이지로 돌아가기"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"닫기"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 패스키를 사용하시겠습니까?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 로그인 정보를 사용하시겠습니까?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"잠긴 비밀번호 관리자"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"탭하여 잠금 해제"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"로그인 정보 없음"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>의 로그인 정보 없음"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"로그인 관리"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"다른 기기에서"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"다른 기기 사용"</string>
diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index 895d0e7..3e172b4 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Башка сырсөздөрдү башкаргычтар"</string>
<string name="close_sheet" msgid="1393792015338908262">"Баракты жабуу"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Мурунку бетке кайтуу"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Жабуу"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган мүмкүндүк алуу ачкычын колдоносузбу?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган кирүү параметрин колдоносузбу?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Кулпуланган сырсөздөрдү башкаргычтар"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Кулпусун ачуу үчүн таптаңыз"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Аккаунтка кирүү тууралуу маалымат жок"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтунда кирүү маалыматы жок"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кирүү параметрлерин тескөө"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Башка түзмөктөн"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Башка түзмөктү колдонуу"</string>
diff --git a/packages/CredentialManager/res/values-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml
index 757bf13..f08d522 100644
--- a/packages/CredentialManager/res/values-lo/strings.xml
+++ b/packages/CredentialManager/res/values-lo/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"ຕົວຈັດການລະຫັດຜ່ານອື່ນໆ"</string>
<string name="close_sheet" msgid="1393792015338908262">"ປິດຊີດ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ກັບຄືນໄປຫາໜ້າກ່ອນໜ້ານີ້"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ປິດ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ໃຊ້ກະແຈຜ່ານທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ໃຊ້ການເຂົ້າສູ່ລະບົບທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ຕົວຈັດການລະຫັດຜ່ານທີ່ລັອກໄວ້"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ແຕະເພື່ອປົດລັອກ"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບ"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບໃນ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ຈັດການການເຂົ້າສູ່ລະບົບ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ຈາກອຸປະກອນອື່ນ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ໃຊ້ອຸປະກອນອື່ນ"</string>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index d75993f..71b50a8 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Kitos slaptažodžių tvarkyklės"</string>
<string name="close_sheet" msgid="1393792015338908262">"Uždaryti lapą"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Grįžti į ankstesnį puslapį"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Uždaryti"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Naudoti išsaugotą „passkey“ programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Naudoti išsaugotą prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Užrakintos slaptažodžių tvarkyklės"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Palieskite, kad atrakintumėte"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Prisijungimo informacijos nėra"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nėra prisijungimo informacijos <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Tvarkyti prisijungimo informaciją"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Naudojant kitą įrenginį"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Naudoti kitą įrenginį"</string>
diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml
index 01c6d55..86a7b8a 100644
--- a/packages/CredentialManager/res/values-lv/strings.xml
+++ b/packages/CredentialManager/res/values-lv/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Citi paroļu pārvaldnieki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Aizvērt lapu"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Atgriezties iepriekšējā lapā"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Aizvērt"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vai izmantot saglabāto piekļuves atslēgu lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vai izmantot saglabāto pierakstīšanās informāciju lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Paroļu pārvaldnieki, kuros nepieciešams autentificēties"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Pieskarieties, lai atbloķētu"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nav pierakstīšanās informācijas"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontā <xliff:g id="SOURCE">%1$s</xliff:g> nav pierakstīšanās informācijas."</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pierakstīšanās informācijas pārvaldība"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"No citas ierīces"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Izmantot citu ierīci"</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index a844bc9..393bca1 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Други управници со лозинки"</string>
<string name="close_sheet" msgid="1393792015338908262">"Затворете го листот"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Врати се на претходната страница"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Затвори"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се користи вашиот зачуван криптографски клуч за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се користи вашето зачувано најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заклучени управници со лозинки"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Допрете за да отклучите"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема податоци за најавување"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема податоци за најавување во <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управувајте со најавувањата"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Од друг уред"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Употребете друг уред"</string>
diff --git a/packages/CredentialManager/res/values-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml
index de88b28..efe614c 100644
--- a/packages/CredentialManager/res/values-ml/strings.xml
+++ b/packages/CredentialManager/res/values-ml/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"ഷീറ്റ് അടയ്ക്കുക"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"മുമ്പത്തെ പേജിലേക്ക് മടങ്ങുക"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"അടയ്ക്കുക"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച പാസ്കീ ഉപയോഗിക്കണോ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച സൈൻ ഇൻ ഉപയോഗിക്കണോ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി ഒരു സംരക്ഷിച്ച സൈൻ ഇൻ തിരഞ്ഞെടുക്കുക"</string>
diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index ee5d66f..6c7ba7a 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Нууц үгний бусад менежер"</string>
<string name="close_sheet" msgid="1393792015338908262">"Хүснэгтийг хаах"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Өмнөх хуудас руу буцах"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Хаах"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д өөрийн хадгалсан passkey-г ашиглах уу?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нэвтрэх мэдээллээ ашиглах уу?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Түгжээтэй нууц үгний менежерүүд"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Түгжээг тайлахын тулд товшино уу"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ямар ч нэвтрэх мэдээлэл байхгүй"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-д ямар ч нэвтрэх мэдээлэл алга"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Нэвтрэлтийг удирдах"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Өөр төхөөрөмжөөс"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Өөр төхөөрөмж ашиглах"</string>
diff --git a/packages/CredentialManager/res/values-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml
index bc03212..ca0480c 100644
--- a/packages/CredentialManager/res/values-mr/strings.xml
+++ b/packages/CredentialManager/res/values-mr/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"इतर पासवर्ड व्यवस्थापक"</string>
<string name="close_sheet" msgid="1393792015338908262">"शीट बंद करा"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"मागील पेजवर परत जा"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करा"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमची सेव्ह केलेली पासकी वापरायची का?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमचे सेव्ह केलेले साइन-इन वापरायचे का?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक केलेले पासवर्ड व्यवस्थापक"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करण्यासाठी टॅप करा"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन माहिती नाही"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मध्ये कोणतीही साइन-इन माहिती नाही"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन-इन व्यवस्थापित करा"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"दुसऱ्या डिव्हाइस वरून"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"वेगळे डिव्हाइस वापरा"</string>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index ab2d9536..7719f91 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Tutup helaian"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci laluan anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan maklumat log masuk anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pilih log masuk yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index 92a9e49..9b60d5c 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"အခြားစကားဝှက်မန်နေဂျာများ"</string>
<string name="close_sheet" msgid="1393792015338908262">"စာမျက်နှာ ပိတ်ရန်"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ယခင်စာမျက်နှာကို ပြန်သွားပါ"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ပိတ်ရန်"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလျှို့ဝှက်ကီး သုံးမလား။"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလက်မှတ်ထိုးဝင်မှု သုံးမလား။"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"လော့ခ်ချထားသည့် စကားဝှက်မန်နေဂျာများ"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ဖွင့်ရန် တို့ပါ"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"လက်မှတ်ထိုးဝင်သည့် အချက်အလက် မရှိပါ"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> တွင် လက်မှတ်ထိုးဝင်ရန်အချက်အလက် မရှိပါ"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"လက်မှတ်ထိုးဝင်မှုများ စီမံခြင်း"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"စက်နောက်တစ်ခုမှ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"အခြားစက်သုံးရန်"</string>
diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index ac8f7c1..88692cb 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Andre løsninger for passordlagring"</string>
<string name="close_sheet" msgid="1393792015338908262">"Lukk arket"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbake til den forrige siden"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Lukk"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruke den lagrede tilgangsnøkkelen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruke den lagrede påloggingen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste løsninger for passordlagring"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trykk for å låse opp"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen påloggingsinformasjon"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ingen påloggingsinformasjon i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer pålogginger"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en annen enhet"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Bruk en annen enhet"</string>
diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml
index 70ae649..45c9f8c 100644
--- a/packages/CredentialManager/res/values-ne/strings.xml
+++ b/packages/CredentialManager/res/values-ne/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"अन्य पासवर्ड म्यानेजरहरू"</string>
<string name="close_sheet" msgid="1393792015338908262">"पाना बन्द गर्नुहोस्"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"अघिल्लो पेजमा फर्कनुहोस्"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"बन्द गर्नुहोस्"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"आफूले सेभ गरेको पासकी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"आफूले सेभ गरेको साइन इनसम्बन्धी जानकारी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लक गरिएका पासवर्ड म्यानेजरहरू"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलक गर्न ट्याप गर्नुहोस्"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन गर्न प्रयोग गरिनु पर्ने जानकारी उपलब्ध छैन"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मा साइन इन गर्नेसम्बन्धी कुनै पनि जानकारी छैन"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इनसम्बन्धी विकल्पहरू व्यवस्थापन गर्नुहोस्"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"अर्को डिभाइसका लागि"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"अर्कै डिभाइस प्रयोग गरी हेर्नुहोस्"</string>
diff --git a/packages/CredentialManager/res/values-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml
index f3d7288..32307ea2 100644
--- a/packages/CredentialManager/res/values-nl/strings.xml
+++ b/packages/CredentialManager/res/values-nl/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Andere wachtwoordmanagers"</string>
<string name="close_sheet" msgid="1393792015338908262">"Blad sluiten"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Ga terug naar de vorige pagina"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Sluiten"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Je opgeslagen toegangssleutel voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Je opgeslagen inloggegevens voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vergrendelde wachtwoordmanagers"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tik om te ontgrendelen"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Geen inloggegevens"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Geen inloggevens in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Inloggegevens beheren"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via een ander apparaat"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Een ander apparaat gebruiken"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 539b3dd..953e9b2 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"ଅନ୍ୟ Password Manager"</string>
<string name="close_sheet" msgid="1393792015338908262">"ସିଟ ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ପୂର୍ବବର୍ତ୍ତୀ ପୃଷ୍ଠାକୁ ଫେରନ୍ତୁ"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ପାସକୀ ବ୍ୟବହାର କରିବେ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ସାଇନ-ଇନ ବ୍ୟବହାର କରିବେ?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ଲକ ଥିବା Password Manager"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ଅନଲକ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>ରେ କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ସାଇନ-ଇନ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ଅନ୍ୟ ଏକ ଡିଭାଇସରୁ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ଏକ ଭିନ୍ନ ଡିଭାଇସ ବ୍ୟବହାର କରନ୍ତୁ"</string>
diff --git a/packages/CredentialManager/res/values-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml
index 7e4676a..2dd6a2c 100644
--- a/packages/CredentialManager/res/values-pa/strings.xml
+++ b/packages/CredentialManager/res/values-pa/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"ਹੋਰ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
<string name="close_sheet" msgid="1393792015338908262">"ਸ਼ੀਟ ਬੰਦ ਕਰੋ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ਪਿਛਲੇ ਪੰਨੇ \'ਤੇ ਵਾਪਸ ਜਾਓ"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ਬੰਦ ਕਰੋ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਪਾਸਕੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ਲਾਕ ਕੀਤੇ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ਵਿੱਚ ਕੋਈ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਨਹੀਂ"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ਸਾਈਨ-ਇਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ਹੋਰ ਡੀਵਾਈਸ ਤੋਂ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ਵੱਖਰੇ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index c77d846..74a0d8f 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Inne menedżery haseł"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zamknij arkusz"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Wróć do poprzedniej strony"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zamknij"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Użyć zapisanego klucza dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Użyć zapisanych danych logowania dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zablokowane menedżery haseł"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kliknij, aby odblokować"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Brak danych logowania"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>: brak danych logowania"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Zarządzanie danymi logowania"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na innym urządzeniu"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Użyj innego urządzenia"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index 90433e1..9eaf99b 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 1abc85d..ad927e0 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Fechar folha"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volte à página anterior"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar a sua token de acesso guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar o seu início de sessão guardado na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolha um início de sessão guardado para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml
index 90433e1..9eaf99b 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml
index 11b3b49..198ff1d 100644
--- a/packages/CredentialManager/res/values-ro/strings.xml
+++ b/packages/CredentialManager/res/values-ro/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Alți manageri de parole"</string>
<string name="close_sheet" msgid="1393792015338908262">"Închide foaia"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revino la pagina precedentă"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Închide"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Folosești cheia de acces salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Folosești datele de conectare salvate pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Manageri de parole blocate"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Atinge pentru a debloca"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Fără informații de conectare"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nu există informații de conectare în contul <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionează acreditările"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De pe alt dispozitiv"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Folosește alt dispozitiv"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index c7d253e..846df54 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Другие менеджеры паролей"</string>
<string name="close_sheet" msgid="1393792015338908262">"Закрыть лист"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вернуться на предыдущую страницу"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыть"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Использовать сохраненный ключ доступа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Использовать сохраненные учетные данные для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблокированные менеджеры паролей"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Нажмите для разблокировки"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Необходимо ввести учетные данные"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"В аккаунте <xliff:g id="SOURCE">%1$s</xliff:g> нет учетных данных"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление входом"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"С другого устройства"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Использовать другое устройство"</string>
diff --git a/packages/CredentialManager/res/values-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml
index 36ce3f8..1df8ea2 100644
--- a/packages/CredentialManager/res/values-si/strings.xml
+++ b/packages/CredentialManager/res/values-si/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"වෙනත් මුරපද කළමනාකරුවන්"</string>
<string name="close_sheet" msgid="1393792015338908262">"පත්රය වසන්න"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"පෙර පිටුවට ආපසු යන්න"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"වසන්න"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි මුරයතුර භාවිතා කරන්න ද?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි පුරනය භාවිතා කරන්න ද?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"අගුළු දැමූ මුරපද කළමනාකරුවන්"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"අගුළු හැරීමට තට්ටු කරන්න"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"පුරනය වීමේ තතු නැත"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> තුළ පුරනය වීමේ තතු නැත"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"පුරනය වීම් කළමනාකරණය කරන්න"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"වෙනත් උපාංගයකින්"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"වෙනස් උපාංගයක් භාවිතා කරන්න"</string>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 09bf265..eb18796 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Iní správcovia hesiel"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zavrieť hárok"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Prejsť späť na predchádzajúcu stránku"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zavrieť"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložený prístupový kľúč?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložené prihlasovacie údaje?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Správcovia uzamknutých hesiel"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Odomknúť klepnutím"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žiadne prihlasovacie údaje"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Žiadne prihlasovacie údaje v zdroji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovať prihlasovacie údaje"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z iného zariadenia"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použiť iné zariadenie"</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index 29b6410..15bcbae 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Zapri list"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Nazaj na prejšnjo stran"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Zapri"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite uporabiti shranjeni ključ za dostop do aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite uporabiti shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Izberite shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 6650668..1e46538 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Menaxherët e tjerë të fjalëkalimeve"</string>
<string name="close_sheet" msgid="1393792015338908262">"Mbyll fletën"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kthehu te faqja e mëparshme"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Mbyll"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Të përdoret fjalëkalimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Të përdoret identifikimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menaxherët e fjalëkalimeve të kyçura"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trokit për të shkyçur"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nuk ka informacione për identifikimin"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nuk ka informacione regjistrimi në <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Identifikimet e menaxhimit"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Nga një pajisje tjetër"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Përdor një pajisje tjetër"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index 877d45c..bbb5463 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Други менаџери лозинки"</string>
<string name="close_sheet" msgid="1393792015338908262">"Затворите табелу"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вратите се на претходну страницу"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Затворите"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Желите да користите сачувани приступни кôд за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Желите да користите сачуване податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Менаџери закључаних лозинки"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Додирните да бисте откључали"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема података за пријављивање"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема података за пријављивање у: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управљајте пријављивањима"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Са другог уређаја"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Користи други уређај"</string>
diff --git a/packages/CredentialManager/res/values-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml
index 9ec317e..3d85e14 100644
--- a/packages/CredentialManager/res/values-sv/strings.xml
+++ b/packages/CredentialManager/res/values-sv/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Andra lösenordshanterare"</string>
<string name="close_sheet" msgid="1393792015338908262">"Stäng kalkylarket"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tillbaka till föregående sida"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Stäng"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vill du använda din sparade nyckel för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vill du använda dina sparade inloggningsuppgifter för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låsta lösenordshanterare"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryck för att låsa upp"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen inloggningsinformation"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Det finns inga inloggningsuppgifter i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Hantera inloggningar"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via en annan enhet"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Använd en annan enhet"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 1a5499c..f0f1db5 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Vidhibiti vinginevyo vya manenosiri"</string>
<string name="close_sheet" msgid="1393792015338908262">"Funga laha"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Rudi kwenye ukurasa uliotangulia"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Funga"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Ungependa kutumia ufunguo wa siri uliohifadhiwa wa<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Ungependa kutumia kitambulisho kilichohifadhiwa cha kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vidhibiti vya manenosiri vilivyofungwa"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Gusa ili ufungue"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Hakuna maelezo ya kuingia katika akaunti"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Hakuna maelezo ya kuingia katika akaunti kwenye <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Dhibiti michakato ya kuingia katika akaunti"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kutoka kwenye kifaa kingine"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Tumia kifaa tofauti"</string>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index 19a871f..09a4fcb 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"பிற கடவுச்சொல் நிர்வாகிகள்"</string>
<string name="close_sheet" msgid="1393792015338908262">"ஷீட்டை மூடும்"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"முந்தைய பக்கத்திற்குச் செல்லும்"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"மூடும்"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட கடவுக்குறியீட்டைப் பயன்படுத்தவா?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட உள்நுழைவுத் தகவலைப் பயன்படுத்தவா?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"பூட்டப்பட்ட கடவுச்சொல் நிர்வாகிகள்"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"அன்லாக் செய்ய தட்டவும்"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"உள்நுழைவு விவரங்கள் இல்லை"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> கணக்கில் உள்நுழைவு விவரங்கள் இல்லை"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"உள்நுழைவுகளை நிர்வகித்தல்"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"மற்றொரு சாதனத்திலிருந்து பயன்படுத்து"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"வேறு சாதனத்தைப் பயன்படுத்து"</string>
diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index 04ee0fe..e93ff20 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"షీట్ను మూసివేయండి"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"మునుపటి పేజీకి తిరిగి వెళ్లండి"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"మూసివేస్తుంది"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్-కీ వివరాలను ఉపయోగించాలా?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీరు సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఉపయోగించాలా?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఎంచుకోండి"</string>
diff --git a/packages/CredentialManager/res/values-th/strings.xml b/packages/CredentialManager/res/values-th/strings.xml
index 29e87a0..e44a66d 100644
--- a/packages/CredentialManager/res/values-th/strings.xml
+++ b/packages/CredentialManager/res/values-th/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"เครื่องมือจัดการรหัสผ่านอื่นๆ"</string>
<string name="close_sheet" msgid="1393792015338908262">"ปิดชีต"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"กลับไปยังหน้าก่อนหน้า"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ปิด"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ใช้พาสคีย์ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ใช้การลงชื่อเข้าใช้ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"เครื่องมือจัดการรหัสผ่านที่ล็อกไว้"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"แตะเพื่อปลดล็อก"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ไม่มีข้อมูลการลงชื่อเข้าใช้"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"ไม่มีข้อมูลการลงชื่อเข้าใช้ใน <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"จัดการการลงชื่อเข้าใช้"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"จากอุปกรณ์อื่น"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ใช้อุปกรณ์อื่น"</string>
diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index 773039f..6b48af1 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Iba pang password manager"</string>
<string name="close_sheet" msgid="1393792015338908262">"Isara ang sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Bumalik sa nakaraang page"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Isara"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gamitin ang iyong naka-save na passkey para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gamitin ang iyong naka-save na sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Mga naka-lock na password manager"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"I-tap para i-unlock"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Walang impormasyon sa pag-sign in"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Walang impormasyon sa pag-sign in sa <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pamahalaan ang mga sign-in"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Mula sa ibang device"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gumamit ng ibang device"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 083add3..b0a354c 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Diğer şifre yöneticileri"</string>
<string name="close_sheet" msgid="1393792015338908262">"Sayfayı kapat"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Önceki sayfaya geri dön"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Kapat"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifre anahtarınız kullanılsın mı?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgileriniz kullanılsın mı?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Kilitli şifre yöneticileri"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kilidi açmak için dokunun"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Oturum açma bilgisi yok"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> hesabında oturum açma bilgisi yok"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Oturum açma bilgilerini yönetin"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Başka bir cihazdan"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Farklı bir cihaz kullan"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index dd112e03..ec12bc6 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Інші менеджери паролів"</string>
<string name="close_sheet" msgid="1393792015338908262">"Закрити аркуш"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Повернутися на попередню сторінку"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Закрити"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Використати збережений ключ доступу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Використати збережені дані для входу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблоковані менеджери паролів"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Торкніться, щоб розблокувати"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Немає даних для входу"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Немає даних для входу в обліковий запис <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Керування даними для входу"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншого пристрою"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Використовувати інший пристрій"</string>
diff --git a/packages/CredentialManager/res/values-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml
index 3a704fe..b4bf77f 100644
--- a/packages/CredentialManager/res/values-ur/strings.xml
+++ b/packages/CredentialManager/res/values-ur/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"دیگر پاس ورڈ مینیجرز"</string>
<string name="close_sheet" msgid="1393792015338908262">"شیٹ بند کریں"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"گزشتہ صفحے پر واپس جائیں"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"بند کریں"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنی محفوظ کردہ پاس کی استعمال کریں؟"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنے محفوظ کردہ سائن ان کو استعمال کریں؟"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مقفل کردہ پاس ورڈ مینیجرز"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"غیر مقفل کرنے کیلئے تھپتھپائیں"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"سائن ان کی کوئی معلومات نہیں"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> میں سائن ان کی کوئی معلومات نہیں ہے"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"سائن انز کا نظم کریں"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"دوسرے آلے سے"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ایک مختلف آلہ استعمال کریں"</string>
diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index 8248d52..92c40ee 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -48,6 +48,8 @@
<string name="close_sheet" msgid="1393792015338908262">"Varaqni yopish"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Avvalgi sahifaga qaytish"</string>
<string name="accessibility_close_button" msgid="1163435587545377687">"Yopish"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan kalit ishlatilsinmi?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan maʼlumotlar ishlatilsinmi?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> hisob maʼlumotlarini tanlang"</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index 058e207..dd0aeed 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Trình quản lý mật khẩu khác"</string>
<string name="close_sheet" msgid="1393792015338908262">"Đóng trang tính"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Quay lại trang trước"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Đóng"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Dùng mã xác thực bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Dùng thông tin đăng nhập bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Trình quản lý mật khẩu đã khoá"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Nhấn để mở khoá"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Không có thông tin đăng nhập"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Không có thông tin đăng nhập trong <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Quản lý thông tin đăng nhập"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Từ một thiết bị khác"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Dùng thiết bị khác"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index 976ef57..87bdce3e 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"其他密码管理工具"</string>
<string name="close_sheet" msgid="1393792015338908262">"关闭工作表"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一页"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"关闭"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"将您已保存的通行密钥用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"将您已保存的登录信息用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已锁定的密码管理工具"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"点按即可解锁"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"无登录信息"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中没有任何登录信息"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登录信息"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"通过另一台设备"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他设备"</string>
diff --git a/packages/CredentialManager/res/values-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml
index 0014d7d..b8d5fc56 100644
--- a/packages/CredentialManager/res/values-zh-rHK/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
<string name="close_sheet" msgid="1393792015338908262">"閂工作表"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密鑰嗎?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資料嗎?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕按即可解鎖"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資料"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資料"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資料"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index 6173584..885753a 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
<string name="close_sheet" msgid="1393792015338908262">"關閉功能表"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼金鑰嗎?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資訊嗎?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕觸即可解鎖"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資訊"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資訊"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資訊"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml
index a1c3230..f077d57 100644
--- a/packages/CredentialManager/res/values-zu/strings.xml
+++ b/packages/CredentialManager/res/values-zu/strings.xml
@@ -47,7 +47,8 @@
<string name="other_password_manager" msgid="565790221427004141">"Abanye abaphathi bephasiwedi"</string>
<string name="close_sheet" msgid="1393792015338908262">"Vala ishidi"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Buyela emuva ekhasini langaphambilini"</string>
- <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Vala"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
<skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Sebenzisa ukhiye wakho wokungena olondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Sebenzisa ukungena kwakho ngemvume okulondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Abaphathi bephasiwedi abakhiyiwe"</string>
<string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Thepha ukuze uvule"</string>
<string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Alukho ulwazi lokungena ngemvume"</string>
- <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
- <skip />
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Alukho ulwazi lokungena ngemvume lwe-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Phatha ukungena ngemvume"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kusukela kwenye idivayisi"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Sebenzisa idivayisi ehlukile"</string>
diff --git a/packages/CredentialManager/res/values/themes.xml b/packages/CredentialManager/res/values/themes.xml
index c7e4796..82aebb7 100644
--- a/packages/CredentialManager/res/values/themes.xml
+++ b/packages/CredentialManager/res/values/themes.xml
@@ -5,7 +5,5 @@
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
- <item name="android:statusBarColor">@android:color/transparent</item>
- <item name="android:navigationBarColor">@android:color/transparent</item>
</style>
</resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 0e604ce..a2d1e4d 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -73,7 +73,7 @@
requestInfo = intent.extras?.getParcelable(
RequestInfo.EXTRA_REQUEST_INFO,
RequestInfo::class.java
- ) ?: testCreatePasskeyRequestInfo()
+ ) ?: testGetRequestInfo()
val originName: String? = when (requestInfo.type) {
RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
@@ -407,8 +407,8 @@
val credentialData = request.credentialData
return RequestInfo.newCreateRequestInfo(
Binder(),
- CreateCredentialRequest.Builder(credentialData, Bundle())
- .setType("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL")
+ CreateCredentialRequest.Builder("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
+ credentialData, Bundle())
.setIsSystemProviderRequired(false)
.setAlwaysSendAppInfoToProvider(true)
.build(),
@@ -420,8 +420,8 @@
val request = CreatePasswordRequest("beckett-bakert@gmail.com", "password123")
return RequestInfo.newCreateRequestInfo(
Binder(),
- CreateCredentialRequest.Builder(request.credentialData, request.candidateQueryData)
- .setType(TYPE_PASSWORD_CREDENTIAL)
+ CreateCredentialRequest.Builder(TYPE_PASSWORD_CREDENTIAL,
+ request.credentialData, request.candidateQueryData)
.setIsSystemProviderRequired(false)
.setAlwaysSendAppInfoToProvider(true)
.build(),
@@ -438,8 +438,7 @@
)
return RequestInfo.newCreateRequestInfo(
Binder(),
- CreateCredentialRequest.Builder(data, Bundle())
- .setType("other-sign-ins")
+ CreateCredentialRequest.Builder("other-sign-ins", data, Bundle())
.setIsSystemProviderRequired(false)
.setAlwaysSendAppInfoToProvider(true)
.build(),
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index a834994..43912c2 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -52,9 +52,7 @@
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.CredentialOption
import androidx.credentials.CreatePublicKeyCredentialRequest
-import androidx.credentials.CreatePublicKeyCredentialRequestPrivileged
import androidx.credentials.GetPublicKeyCredentialOption
-import androidx.credentials.GetPublicKeyCredentialOptionPrivileged
import androidx.credentials.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import androidx.credentials.provider.Action
import androidx.credentials.provider.AuthenticationAction
@@ -186,8 +184,6 @@
)
if (credentialOptionJetpack is GetPublicKeyCredentialOption) {
credentialOptionJetpack.preferImmediatelyAvailableCredentials
- } else if (credentialOptionJetpack is GetPublicKeyCredentialOptionPrivileged) {
- credentialOptionJetpack.preferImmediatelyAvailableCredentials
} else {
false
}
@@ -224,7 +220,7 @@
credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
userName = credentialEntry.username.toString(),
displayName = credentialEntry.displayName?.toString(),
- icon = credentialEntry.icon?.loadDrawable(context),
+ icon = credentialEntry.icon.loadDrawable(context),
lastUsedTimeMillis = credentialEntry.lastUsedTime,
))
}
@@ -239,7 +235,7 @@
credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
userName = credentialEntry.username.toString(),
displayName = credentialEntry.displayName?.toString(),
- icon = credentialEntry.icon?.loadDrawable(context),
+ icon = credentialEntry.icon.loadDrawable(context),
lastUsedTimeMillis = credentialEntry.lastUsedTime,
))
}
@@ -254,7 +250,7 @@
credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
userName = credentialEntry.title.toString(),
displayName = credentialEntry.subtitle?.toString(),
- icon = credentialEntry.icon?.loadDrawable(context),
+ icon = credentialEntry.icon.loadDrawable(context),
lastUsedTimeMillis = credentialEntry.lastUsedTime,
))
}
@@ -436,7 +432,7 @@
createCredentialRequestJetpack.password,
CredentialType.PASSWORD,
appLabel,
- context.getDrawable(R.drawable.ic_password) ?: return null,
+ context.getDrawable(R.drawable.ic_password_24) ?: return null,
preferImmediatelyAvailableCredentials = false,
)
is CreatePublicKeyCredentialRequest -> {
@@ -448,27 +444,18 @@
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
)
}
- is CreatePublicKeyCredentialRequestPrivileged -> {
- newRequestDisplayInfoFromPasskeyJson(
- requestJson = createCredentialRequestJetpack.requestJson,
- appLabel = appLabel,
- context = context,
- preferImmediatelyAvailableCredentials =
- createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
- )
- }
is CreateCustomCredentialRequest -> {
// TODO: directly use the display info once made public
val displayInfo = CreateCredentialRequest.DisplayInfo
.parseFromCredentialDataBundle(createCredentialRequest.credentialData)
?: return null
RequestDisplayInfo(
- title = displayInfo.userId,
- subtitle = displayInfo.userDisplayName,
+ title = displayInfo.userId.toString(),
+ subtitle = displayInfo.userDisplayName?.toString(),
type = CredentialType.UNKNOWN,
appName = appLabel,
typeIcon = displayInfo.credentialTypeIcon?.loadDrawable(context)
- ?: context.getDrawable(R.drawable.ic_other_sign_in) ?: return null,
+ ?: context.getDrawable(R.drawable.ic_other_sign_in_24) ?: return null,
preferImmediatelyAvailableCredentials = false,
)
}
@@ -656,7 +643,7 @@
displayName,
CredentialType.PASSKEY,
appLabel,
- context.getDrawable(R.drawable.ic_passkey) ?: return null,
+ context.getDrawable(R.drawable.ic_passkey_24) ?: return null,
preferImmediatelyAvailableCredentials,
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
index 9216429..75b12ff 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
@@ -25,7 +25,10 @@
import android.credentials.ui.AuthenticationEntry
import android.credentials.ui.Entry
import android.net.Uri
+import android.os.Bundle
import android.provider.Settings
+import androidx.credentials.provider.BeginGetPasswordOption
+import androidx.credentials.provider.BeginGetPublicKeyCredentialOption
import androidx.credentials.provider.CreateEntry
import androidx.credentials.provider.PasswordCredentialEntry
import androidx.credentials.provider.PublicKeyCredentialEntry
@@ -82,7 +85,9 @@
return Entry(
key,
subkey,
- RemoteCredentialEntry(pendingIntent).slice
+ RemoteCredentialEntry(pendingIntent, BeginGetPublicKeyCredentialOption(
+ Bundle(), "id", "requestjson"
+ )).slice
)
}
@@ -137,7 +142,8 @@
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_ONE_SHOT)
)
- val passwordEntry = PasswordCredentialEntry.Builder(context, userName, pendingIntent)
+ val passwordEntry = PasswordCredentialEntry.Builder(
+ context, userName, pendingIntent, BeginGetPasswordOption(Bundle(), "id"))
.setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
return Entry(key, subkey, passwordEntry.slice, Intent())
}
@@ -158,8 +164,12 @@
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_ONE_SHOT)
)
- val passkeyEntry = PublicKeyCredentialEntry.Builder(context, userName, pendingIntent)
- .setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
+ val passkeyEntry = PublicKeyCredentialEntry.Builder(
+ context,
+ userName,
+ pendingIntent,
+ BeginGetPublicKeyCredentialOption(Bundle(), "id", "requestjson")
+ ).setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
return Entry(key, subkey, passkeyEntry.slice, Intent())
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
index 335d58a..307d953 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
@@ -306,10 +306,6 @@
* @param sheetContentColor The preferred content color provided by the bottom sheet to its
* children. Defaults to the matching content color for [sheetBackgroundColor], or if that is not
* a color from the theme, this will keep the same content color set above the bottom sheet.
- * @param scrimColor The color of the scrim that is applied to the rest of the screen when the
- * bottom sheet is visible. If the color passed is [Color.Unspecified], then a scrim will no
- * longer be applied and the bottom sheet will not block interaction with the rest of the screen
- * when visible.
* @param content The content of rest of the screen.
*/
@Composable
@@ -322,7 +318,6 @@
sheetElevation: Dp = ModalBottomSheetDefaults.Elevation,
sheetBackgroundColor: Color = MaterialTheme.colorScheme.surface,
sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
- scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
content: @Composable () -> Unit
) {
val scope = rememberCoroutineScope()
@@ -332,7 +327,7 @@
Box(Modifier.fillMaxSize()) {
content()
Scrim(
- color = scrimColor,
+ color = ModalBottomSheetDefaults.scrimColor,
onDismiss = {
if (sheetState.confirmStateChange(Hidden)) {
scope.launch { sheetState.hide() }
@@ -505,5 +500,5 @@
*/
val scrimColor: Color
@Composable
- get() = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.32f)
+ get() = MaterialTheme.colorScheme.scrim.copy(alpha = .32f)
}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
index c4d96cc..0cb2bb0 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
@@ -39,11 +39,12 @@
skipHalfExpanded = true
)
ModalBottomSheetLayout(
- sheetBackgroundColor = MaterialTheme.colorScheme.surface,
+ sheetBackgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
+ ElevationTokens.Level1
+ ),
modifier = Modifier.background(Color.Transparent),
sheetState = state,
sheetContent = sheetContent,
- scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
sheetShape = EntryShape.TopRoundedCorner,
) {}
LaunchedEffect(state.currentValue) {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
index a622e07..c535268 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
@@ -16,11 +16,13 @@
package com.android.credentialmanager.common.ui
-import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
@@ -29,6 +31,7 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.ui.theme.Shapes
/**
* Container card for the whole sheet.
@@ -40,7 +43,8 @@
fun SheetContainerCard(
topAppBar: (@Composable () -> Unit)? = null,
modifier: Modifier = Modifier,
- content: @Composable ColumnScope.() -> Unit,
+ contentVerticalArrangement: Arrangement.Vertical = Arrangement.Top,
+ content: LazyListScope.() -> Unit,
) {
Card(
modifier = modifier.fillMaxWidth().wrapContentHeight(),
@@ -54,7 +58,7 @@
if (topAppBar != null) {
topAppBar()
}
- Column(
+ LazyColumn(
modifier = Modifier.padding(
start = 24.dp,
end = 24.dp,
@@ -63,6 +67,7 @@
).fillMaxWidth().wrapContentHeight(),
horizontalAlignment = Alignment.CenterHorizontally,
content = content,
+ verticalArrangement = contentVerticalArrangement,
)
}
}
@@ -79,7 +84,7 @@
) {
Card(
modifier = modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
+ shape = Shapes.medium,
border = null,
colors = CardDefaults.cardColors(
containerColor = Color.Transparent,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Columns.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Columns.kt
deleted file mode 100644
index 23ad53c..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Columns.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2023 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.credentialmanager.common.ui
-
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyListScope
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.unit.dp
-
-@Composable
-fun EntryListColumn(content: LazyListScope.() -> Unit) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp),
- content = content,
- )
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
index 0eaaf97..1e2a280 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -74,6 +74,12 @@
/** If true, draws a trailing lock icon. */
isLockedAuthEntry: Boolean = false,
) {
+ val iconPadding = Modifier.wrapContentSize().padding(
+ // Horizontal padding should be 16dp, but the suggestion chip itself
+ // has 8dp horizontal elements padding
+ start = 8.dp, top = 16.dp, bottom = 16.dp
+ )
+ val iconSize = Modifier.size(24.dp)
SuggestionChip(
modifier = modifier.fillMaxWidth().wrapContentHeight(),
onClick = onClick,
@@ -81,7 +87,11 @@
label = {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(all = 16.dp),
+ modifier = Modifier.fillMaxWidth().padding(
+ // Total end padding should be 16dp, but the suggestion chip itself
+ // has 8dp horizontal elements padding
+ horizontal = 8.dp, vertical = 16.dp,
+ ),
verticalAlignment = Alignment.CenterVertically,
) {
Column(modifier = Modifier.wrapContentSize()) {
@@ -121,7 +131,7 @@
}
}
if (isLockedAuthEntry) {
- Box(modifier = Modifier.wrapContentSize().padding(end = 16.dp)) {
+ Box(modifier = Modifier.wrapContentSize()) {
Icon(
imageVector = Icons.Outlined.Lock,
// Decorative purpose only.
@@ -137,10 +147,9 @@
if (iconImageBitmap != null) {
if (shouldApplyIconImageBitmapTint) {
{
- Box(modifier = Modifier.wrapContentSize()
- .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+ Box(modifier = iconPadding) {
Icon(
- modifier = Modifier.size(24.dp),
+ modifier = iconSize,
bitmap = iconImageBitmap,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
// Decorative purpose only.
@@ -150,10 +159,9 @@
}
} else {
{
- Box(modifier = Modifier.wrapContentSize()
- .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+ Box(modifier = iconPadding) {
Image(
- modifier = Modifier.size(24.dp),
+ modifier = iconSize,
bitmap = iconImageBitmap,
// Decorative purpose only.
contentDescription = null,
@@ -163,10 +171,9 @@
}
} else if (iconImageVector != null) {
{
- Box(modifier = Modifier.wrapContentSize()
- .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+ Box(modifier = iconPadding) {
Icon(
- modifier = Modifier.size(24.dp),
+ modifier = iconSize,
imageVector = iconImageVector,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
// Decorative purpose only.
@@ -176,10 +183,9 @@
}
} else if (iconPainter != null) {
{
- Box(modifier = Modifier.wrapContentSize()
- .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+ Box(modifier = iconPadding) {
Icon(
- modifier = Modifier.size(24.dp),
+ modifier = iconSize,
painter = iconPainter,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
// Decorative purpose only.
@@ -305,7 +311,7 @@
},
navigationIcon = {
IconButton(
- modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp),
+ modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp).size(48.dp),
onClick = onNavigationIconClicked
) {
Box(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt
new file mode 100644
index 0000000..2f14584
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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.credentialmanager.common.ui
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import com.android.compose.SystemUiController
+import com.android.credentialmanager.common.material.ModalBottomSheetDefaults
+
+@Composable
+fun setTransparentSystemBarsColor(sysUiController: SystemUiController) {
+ sysUiController.setSystemBarsColor(color = Color.Transparent, darkIcons = false)
+}
+
+@Composable
+fun setBottomSheetSystemBarsColor(sysUiController: SystemUiController) {
+ sysUiController.setStatusBarColor(
+ color = ModalBottomSheetDefaults.scrimColor,
+ darkIcons = false
+ )
+ sysUiController.setNavigationBarColor(
+ color = MaterialTheme.colorScheme.surfaceColorAtElevation(
+ ElevationTokens.Level1
+ ),
+ darkIcons = false
+ )
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 379b3e3..5b175bf 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -8,22 +8,23 @@
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.icons.outlined.QrCodeScanner
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
@@ -31,6 +32,7 @@
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.rememberSystemUiController
import com.android.credentialmanager.CredentialSelectorViewModel
import com.android.credentialmanager.R
import com.android.credentialmanager.common.BaseEntry
@@ -43,7 +45,6 @@
import com.android.credentialmanager.common.ui.CredentialContainerCard
import com.android.credentialmanager.common.ui.CtaButtonRow
import com.android.credentialmanager.common.ui.Entry
-import com.android.credentialmanager.common.ui.EntryListColumn
import com.android.credentialmanager.common.ui.HeadlineIcon
import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
import com.android.credentialmanager.common.ui.ModalBottomSheet
@@ -52,6 +53,7 @@
import com.android.credentialmanager.common.ui.SheetContainerCard
import com.android.credentialmanager.common.ui.PasskeyBenefitRow
import com.android.credentialmanager.common.ui.HeadlineText
+import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
@Composable
fun CreateCredentialScreen(
@@ -59,6 +61,8 @@
createCredentialUiState: CreateCredentialUiState,
providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
+ val sysUiController = rememberSystemUiController()
+ setBottomSheetSystemBarsColor(sysUiController)
ModalBottomSheet(
sheetContent = {
// Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
@@ -157,53 +161,67 @@
onLearnMore: () -> Unit,
) {
SheetContainerCard {
- val onboardingImageResource = remember {
- mutableStateOf(R.drawable.ic_passkeys_onboarding)
+ item {
+ val onboardingImageResource = remember {
+ mutableStateOf(R.drawable.ic_passkeys_onboarding)
+ }
+ if (isSystemInDarkTheme()) {
+ onboardingImageResource.value = R.drawable.ic_passkeys_onboarding_dark
+ } else {
+ onboardingImageResource.value = R.drawable.ic_passkeys_onboarding
+ }
+ Row(
+ modifier = Modifier.wrapContentHeight().fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center,
+ ) {
+ Image(
+ painter = painterResource(onboardingImageResource.value),
+ contentDescription = null,
+ modifier = Modifier.size(316.dp, 168.dp)
+ )
+ }
}
- if (isSystemInDarkTheme()) {
- onboardingImageResource.value = R.drawable.ic_passkeys_onboarding_dark
- } else {
- onboardingImageResource.value = R.drawable.ic_passkeys_onboarding
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item { HeadlineText(text = stringResource(R.string.passkey_creation_intro_title)) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ PasskeyBenefitRow(
+ leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_password),
+ text = stringResource(R.string.passkey_creation_intro_body_password),
+ )
}
- Image(
- painter = painterResource(onboardingImageResource.value),
- contentDescription = null,
- modifier = Modifier
- .align(alignment = Alignment.CenterHorizontally).size(316.dp, 168.dp)
- )
- Divider(thickness = 16.dp, color = Color.Transparent)
- HeadlineText(text = stringResource(R.string.passkey_creation_intro_title))
- Divider(thickness = 16.dp, color = Color.Transparent)
- PasskeyBenefitRow(
- leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_password),
- text = stringResource(R.string.passkey_creation_intro_body_password),
- )
- Divider(thickness = 16.dp, color = Color.Transparent)
- PasskeyBenefitRow(
- leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
- text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
- )
- Divider(thickness = 16.dp, color = Color.Transparent)
- PasskeyBenefitRow(
- leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_device),
- text = stringResource(R.string.passkey_creation_intro_body_device),
- )
- Divider(thickness = 24.dp, color = Color.Transparent)
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ PasskeyBenefitRow(
+ leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
+ text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
+ )
+ }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ PasskeyBenefitRow(
+ leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_device),
+ text = stringResource(R.string.passkey_creation_intro_body_device),
+ )
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
- CtaButtonRow(
- leftButton = {
- ActionButton(
- stringResource(R.string.string_learn_more),
- onClick = onLearnMore
- )
- },
- rightButton = {
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- },
- )
+ item {
+ CtaButtonRow(
+ leftButton = {
+ ActionButton(
+ stringResource(R.string.string_learn_more),
+ onClick = onLearnMore
+ )
+ },
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ },
+ )
+ }
}
}
@@ -218,30 +236,32 @@
onMoreOptionsSelected: () -> Unit,
) {
SheetContainerCard {
- HeadlineIcon(bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap())
- Divider(thickness = 16.dp, color = Color.Transparent)
- HeadlineText(
- text = stringResource(
- R.string.choose_provider_title,
- when (requestDisplayInfo.type) {
- CredentialType.PASSKEY ->
- stringResource(R.string.passkeys)
- CredentialType.PASSWORD ->
- stringResource(R.string.passwords)
- CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
- }
+ item { HeadlineIcon(bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ HeadlineText(
+ text = stringResource(
+ R.string.choose_provider_title,
+ when (requestDisplayInfo.type) {
+ CredentialType.PASSKEY ->
+ stringResource(R.string.passkeys)
+ CredentialType.PASSWORD ->
+ stringResource(R.string.passwords)
+ CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
+ }
+ )
)
- )
- Divider(thickness = 24.dp, color = Color.Transparent)
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
- BodyMediumText(text = stringResource(R.string.choose_provider_body))
- Divider(thickness = 16.dp, color = Color.Transparent)
- CredentialContainerCard {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp)
- ) {
- sortedCreateOptionsPairs.forEach { entry ->
- item {
+ item { BodyMediumText(text = stringResource(R.string.choose_provider_body)) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
+ Column(
+ verticalArrangement = Arrangement.spacedBy(2.dp)
+ ) {
+ sortedCreateOptionsPairs.forEach { entry ->
MoreOptionsInfoRow(
requestDisplayInfo = requestDisplayInfo,
providerInfo = entry.second,
@@ -256,8 +276,6 @@
}
)
}
- }
- item {
MoreOptionsDisabledProvidersRow(
disabledProviders = disabledProviderList,
onDisabledProvidersSelected = onDisabledProvidersSelected,
@@ -266,15 +284,17 @@
}
}
if (hasRemoteEntry) {
- Divider(thickness = 24.dp, color = Color.Transparent)
- CtaButtonRow(
- leftButton = {
- ActionButton(
- stringResource(R.string.string_more_options),
- onMoreOptionsSelected
- )
- }
- )
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CtaButtonRow(
+ leftButton = {
+ ActionButton(
+ stringResource(R.string.string_more_options),
+ onMoreOptionsSelected
+ )
+ }
+ )
+ }
}
}
}
@@ -310,14 +330,15 @@
else onBackCreationSelectionButtonSelected,
)
}) {
- Divider(thickness = 16.dp, color = Color.Transparent)
- CredentialContainerCard {
- EntryListColumn {
- // Only in the flows with default provider(not first time use) we can show the
- // createOptions here, or they will be shown on ProviderSelectionCard
- if (hasDefaultProvider) {
- sortedCreateOptionsPairs.forEach { entry ->
- item {
+ item { Divider(thickness = 8.dp, color = Color.Transparent) } // Top app bar has a 8dp
+ // bottom padding already
+ item {
+ CredentialContainerCard {
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+ // Only in the flows with default provider(not first time use) we can show the
+ // createOptions here, or they will be shown on ProviderSelectionCard
+ if (hasDefaultProvider) {
+ sortedCreateOptionsPairs.forEach { entry ->
MoreOptionsInfoRow(
requestDisplayInfo = requestDisplayInfo,
providerInfo = entry.second,
@@ -329,26 +350,23 @@
entry.first
)
)
- })
+ }
+ )
}
- }
- item {
MoreOptionsDisabledProvidersRow(
disabledProviders = disabledProviderList,
onDisabledProvidersSelected =
onDisabledProvidersSelected,
)
}
- }
- enabledProviderList.forEach {
- if (it.remoteEntry != null) {
- item {
+ enabledProviderList.forEach {
+ if (it.remoteEntry != null) {
RemoteEntryRow(
remoteInfo = it.remoteEntry!!,
onRemoteEntrySelected = onRemoteEntrySelected,
)
+ return@forEach
}
- return@forEach
}
}
}
@@ -363,30 +381,34 @@
onUseOnceSelected: () -> Unit,
) {
SheetContainerCard {
- HeadlineIcon(imageVector = Icons.Outlined.NewReleases)
- Divider(thickness = 24.dp, color = Color.Transparent)
- HeadlineText(
- text = stringResource(
- R.string.use_provider_for_all_title,
- providerInfo.displayName
+ item { HeadlineIcon(imageVector = Icons.Outlined.NewReleases) }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ HeadlineText(
+ text = stringResource(
+ R.string.use_provider_for_all_title,
+ providerInfo.displayName
+ )
)
- )
- Divider(thickness = 24.dp, color = Color.Transparent)
- BodyMediumText(text = stringResource(R.string.use_provider_for_all_description))
- CtaButtonRow(
- leftButton = {
- ActionButton(
- stringResource(R.string.use_once),
- onClick = onUseOnceSelected
- )
- },
- rightButton = {
- ConfirmButton(
- stringResource(R.string.set_as_default),
- onClick = onChangeDefaultSelected
- )
- },
- )
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item { BodyMediumText(text = stringResource(R.string.use_provider_for_all_description)) }
+ item {
+ CtaButtonRow(
+ leftButton = {
+ ActionButton(
+ stringResource(R.string.use_once),
+ onClick = onUseOnceSelected
+ )
+ },
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.set_as_default),
+ onClick = onChangeDefaultSelected
+ )
+ },
+ )
+ }
}
}
@@ -402,38 +424,44 @@
hasDefaultProvider: Boolean,
) {
SheetContainerCard {
- HeadlineIcon(
- bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
- tint = Color.Unspecified,
- )
- Divider(thickness = 4.dp, color = Color.Transparent)
- LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName)
- Divider(thickness = 16.dp, color = Color.Transparent)
- HeadlineText(
- text = when (requestDisplayInfo.type) {
- CredentialType.PASSKEY -> stringResource(
- R.string.choose_create_option_passkey_title,
- requestDisplayInfo.appName
- )
- CredentialType.PASSWORD -> stringResource(
- R.string.choose_create_option_password_title,
- requestDisplayInfo.appName
- )
- CredentialType.UNKNOWN -> stringResource(
- R.string.choose_create_option_sign_in_title,
- requestDisplayInfo.appName
- )
- }
- )
- Divider(thickness = 24.dp, color = Color.Transparent)
- CredentialContainerCard {
- PrimaryCreateOptionRow(
- requestDisplayInfo = requestDisplayInfo,
- entryInfo = createOptionInfo,
- onOptionSelected = onOptionSelected
+ item {
+ HeadlineIcon(
+ bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
+ tint = Color.Unspecified,
)
}
- Divider(thickness = 24.dp, color = Color.Transparent)
+ item { Divider(thickness = 4.dp, color = Color.Transparent) }
+ item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ HeadlineText(
+ text = when (requestDisplayInfo.type) {
+ CredentialType.PASSKEY -> stringResource(
+ R.string.choose_create_option_passkey_title,
+ requestDisplayInfo.appName
+ )
+ CredentialType.PASSWORD -> stringResource(
+ R.string.choose_create_option_password_title,
+ requestDisplayInfo.appName
+ )
+ CredentialType.UNKNOWN -> stringResource(
+ R.string.choose_create_option_sign_in_title,
+ requestDisplayInfo.appName
+ )
+ }
+ )
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
+ PrimaryCreateOptionRow(
+ requestDisplayInfo = requestDisplayInfo,
+ entryInfo = createOptionInfo,
+ onOptionSelected = onOptionSelected
+ )
+ }
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
var createOptionsSize = 0
var remoteEntry: RemoteInfo? = null
enabledProviderList.forEach { enabledProvider ->
@@ -450,29 +478,33 @@
} else {
createOptionsSize > 1 || remoteEntry != null
}
- CtaButtonRow(
- leftButton = if (shouldShowMoreOptionsButton) {
- {
- ActionButton(
- stringResource(R.string.string_more_options),
- onMoreOptionsSelected
+ item {
+ CtaButtonRow(
+ leftButton = if (shouldShowMoreOptionsButton) {
+ {
+ ActionButton(
+ stringResource(R.string.string_more_options),
+ onMoreOptionsSelected
+ )
+ }
+ } else null,
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
)
- }
- } else null,
- rightButton = {
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- },
- )
- if (createOptionInfo.footerDescription != null) {
- Divider(
- thickness = 1.dp,
- color = MaterialTheme.colorScheme.outlineVariant,
- modifier = Modifier.padding(vertical = 16.dp)
+ },
)
- BodySmallText(text = createOptionInfo.footerDescription)
+ }
+ if (createOptionInfo.footerDescription != null) {
+ item {
+ Divider(
+ thickness = 1.dp,
+ color = MaterialTheme.colorScheme.outlineVariant,
+ modifier = Modifier.padding(vertical = 16.dp)
+ )
+ }
+ item { BodySmallText(text = createOptionInfo.footerDescription) }
}
}
}
@@ -485,29 +517,30 @@
onConfirm: () -> Unit,
) {
SheetContainerCard {
- HeadlineIcon(painter = painterResource(R.drawable.ic_other_devices))
- Divider(thickness = 16.dp, color = Color.Transparent)
- HeadlineText(text = stringResource(R.string.create_passkey_in_other_device_title))
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- CredentialContainerCard {
- PrimaryCreateOptionRow(
- requestDisplayInfo = requestDisplayInfo,
- entryInfo = activeRemoteEntry,
- onOptionSelected = onOptionSelected
+ item { HeadlineIcon(imageVector = Icons.Outlined.QrCodeScanner) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item { HeadlineText(text = stringResource(R.string.create_passkey_in_other_device_title)) }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
+ PrimaryCreateOptionRow(
+ requestDisplayInfo = requestDisplayInfo,
+ entryInfo = activeRemoteEntry,
+ onOptionSelected = onOptionSelected
+ )
+ }
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CtaButtonRow(
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ },
)
}
- Divider(thickness = 24.dp, color = Color.Transparent)
- CtaButtonRow(
- rightButton = {
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- },
- )
}
}
@@ -515,40 +548,38 @@
fun MoreAboutPasskeysIntroCard(
onBackPasskeyIntroButtonSelected: () -> Unit,
) {
- SheetContainerCard(topAppBar = {
- MoreOptionTopAppBar(
- text = stringResource(R.string.more_about_passkeys_title),
- onNavigationIconClicked = onBackPasskeyIntroButtonSelected,
- )
- }) {
- LazyColumn(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- verticalArrangement = Arrangement.spacedBy(8.dp)
- ) {
- item {
- MoreAboutPasskeySectionHeader(
- text = stringResource(R.string.passwordless_technology_title)
- )
- BodyMediumText(text = stringResource(R.string.passwordless_technology_detail))
- }
- item {
- MoreAboutPasskeySectionHeader(
- text = stringResource(R.string.public_key_cryptography_title)
- )
- BodyMediumText(text = stringResource(R.string.public_key_cryptography_detail))
- }
- item {
- MoreAboutPasskeySectionHeader(
- text = stringResource(R.string.improved_account_security_title)
- )
- BodyMediumText(text = stringResource(R.string.improved_account_security_detail))
- }
- item {
- MoreAboutPasskeySectionHeader(
- text = stringResource(R.string.seamless_transition_title)
- )
- BodyMediumText(text = stringResource(R.string.seamless_transition_detail))
- }
+ SheetContainerCard(
+ topAppBar = {
+ MoreOptionTopAppBar(
+ text = stringResource(R.string.more_about_passkeys_title),
+ onNavigationIconClicked = onBackPasskeyIntroButtonSelected,
+ )
+ },
+ contentVerticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.passwordless_technology_title)
+ )
+ BodyMediumText(text = stringResource(R.string.passwordless_technology_detail))
+ }
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.public_key_cryptography_title)
+ )
+ BodyMediumText(text = stringResource(R.string.public_key_cryptography_detail))
+ }
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.improved_account_security_title)
+ )
+ BodyMediumText(text = stringResource(R.string.improved_account_security_detail))
+ }
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.seamless_transition_title)
+ )
+ BodyMediumText(text = stringResource(R.string.seamless_transition_detail))
}
}
}
@@ -665,7 +696,7 @@
) {
Entry(
onClick = { onRemoteEntrySelected(remoteInfo) },
- iconPainter = painterResource(R.drawable.ic_other_devices),
+ iconImageVector = Icons.Outlined.QrCodeScanner,
entryHeadlineText = stringResource(R.string.another_device),
)
}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 92a6c39..9a826f2 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -27,8 +27,9 @@
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.QrCodeScanner
import androidx.compose.material3.Divider
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
@@ -40,6 +41,7 @@
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.rememberSystemUiController
import com.android.credentialmanager.CredentialSelectorViewModel
import com.android.credentialmanager.R
import com.android.credentialmanager.common.BaseEntry
@@ -58,6 +60,8 @@
import com.android.credentialmanager.common.ui.HeadlineText
import com.android.credentialmanager.common.ui.CredentialListSectionHeader
import com.android.credentialmanager.common.ui.Snackbar
+import com.android.credentialmanager.common.ui.setTransparentSystemBarsColor
+import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
@Composable
fun GetCredentialScreen(
@@ -65,13 +69,16 @@
getCredentialUiState: GetCredentialUiState,
providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
+ val sysUiController = rememberSystemUiController()
if (getCredentialUiState.currentScreenState == GetScreenState.REMOTE_ONLY) {
+ setTransparentSystemBarsColor(sysUiController)
RemoteCredentialSnackBarScreen(
onClick = viewModel::getFlowOnMoreOptionOnSnackBarSelected,
onCancel = viewModel::onUserCancel,
)
} else if (getCredentialUiState.currentScreenState
== GetScreenState.UNLOCKED_AUTH_ENTRIES_ONLY) {
+ setTransparentSystemBarsColor(sysUiController)
EmptyAuthEntrySnackBarScreen(
authenticationEntryList =
getCredentialUiState.providerDisplayInfo.authenticationEntryList,
@@ -79,6 +86,7 @@
onLastLockedAuthEntryNotFound = viewModel::onLastLockedAuthEntryNotFoundError,
)
} else {
+ setBottomSheetSystemBarsColor(sysUiController)
ModalBottomSheet(
sheetContent = {
// Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
@@ -141,70 +149,72 @@
providerDisplayInfo.sortedUserNameToCredentialEntryList
val authenticationEntryList = providerDisplayInfo.authenticationEntryList
SheetContainerCard {
- HeadlineText(
- text = stringResource(
- if (sortedUserNameToCredentialEntryList
- .size == 1 && authenticationEntryList.isEmpty()
- ) {
- if (sortedUserNameToCredentialEntryList.first()
- .sortedCredentialEntryList.first().credentialType
- == CredentialType.PASSKEY
- ) R.string.get_dialog_title_use_passkey_for
- else R.string.get_dialog_title_use_sign_in_for
- } else if (
- sortedUserNameToCredentialEntryList
- .isEmpty() && authenticationEntryList.size == 1
- ) {
- R.string.get_dialog_title_use_sign_in_for
- } else R.string.get_dialog_title_choose_sign_in_for,
- requestDisplayInfo.appName
- ),
- )
- Divider(thickness = 24.dp, color = Color.Transparent)
- CredentialContainerCard {
- val usernameForCredentialSize = sortedUserNameToCredentialEntryList.size
- val authenticationEntrySize = authenticationEntryList.size
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp)
- ) {
- // Show max 4 entries in this primary page
- if (usernameForCredentialSize + authenticationEntrySize <= 4) {
- items(sortedUserNameToCredentialEntryList) {
- CredentialEntryRow(
- credentialEntryInfo = it.sortedCredentialEntryList.first(),
- onEntrySelected = onEntrySelected,
- )
- }
- items(authenticationEntryList) {
- AuthenticationEntryRow(
- authenticationEntryInfo = it,
- onEntrySelected = onEntrySelected,
- )
- }
- } else if (usernameForCredentialSize < 4) {
- items(sortedUserNameToCredentialEntryList) {
- CredentialEntryRow(
- credentialEntryInfo = it.sortedCredentialEntryList.first(),
- onEntrySelected = onEntrySelected,
- )
- }
- items(authenticationEntryList.take(4 - usernameForCredentialSize)) {
- AuthenticationEntryRow(
- authenticationEntryInfo = it,
- onEntrySelected = onEntrySelected,
- )
- }
- } else {
- items(sortedUserNameToCredentialEntryList.take(4)) {
- CredentialEntryRow(
- credentialEntryInfo = it.sortedCredentialEntryList.first(),
- onEntrySelected = onEntrySelected,
- )
+ item {
+ HeadlineText(
+ text = stringResource(
+ if (sortedUserNameToCredentialEntryList
+ .size == 1 && authenticationEntryList.isEmpty()
+ ) {
+ if (sortedUserNameToCredentialEntryList.first()
+ .sortedCredentialEntryList.first().credentialType
+ == CredentialType.PASSKEY
+ ) R.string.get_dialog_title_use_passkey_for
+ else R.string.get_dialog_title_use_sign_in_for
+ } else if (
+ sortedUserNameToCredentialEntryList
+ .isEmpty() && authenticationEntryList.size == 1
+ ) {
+ R.string.get_dialog_title_use_sign_in_for
+ } else R.string.get_dialog_title_choose_sign_in_for,
+ requestDisplayInfo.appName
+ ),
+ )
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+ val usernameForCredentialSize = sortedUserNameToCredentialEntryList.size
+ val authenticationEntrySize = authenticationEntryList.size
+ // Show max 4 entries in this primary page
+ if (usernameForCredentialSize + authenticationEntrySize <= 4) {
+ sortedUserNameToCredentialEntryList.forEach {
+ CredentialEntryRow(
+ credentialEntryInfo = it.sortedCredentialEntryList.first(),
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ authenticationEntryList.forEach {
+ AuthenticationEntryRow(
+ authenticationEntryInfo = it,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ } else if (usernameForCredentialSize < 4) {
+ sortedUserNameToCredentialEntryList.forEach {
+ CredentialEntryRow(
+ credentialEntryInfo = it.sortedCredentialEntryList.first(),
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ authenticationEntryList.take(4 - usernameForCredentialSize).forEach {
+ AuthenticationEntryRow(
+ authenticationEntryInfo = it,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ } else {
+ sortedUserNameToCredentialEntryList.take(4).forEach {
+ CredentialEntryRow(
+ credentialEntryInfo = it.sortedCredentialEntryList.first(),
+ onEntrySelected = onEntrySelected,
+ )
+ }
}
}
}
}
- Divider(thickness = 24.dp, color = Color.Transparent)
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
var totalEntriesCount = sortedUserNameToCredentialEntryList
.flatMap { it.sortedCredentialEntryList }.size + authenticationEntryList
.size + providerInfoList.flatMap { it.actionEntryList }.size
@@ -212,24 +222,26 @@
// Row horizontalArrangement differs on only one actionButton(should place on most
// left)/only one confirmButton(should place on most right)/two buttons exist the same
// time(should be one on the left, one on the right)
- CtaButtonRow(
- leftButton = if (totalEntriesCount > 1) {
- {
- ActionButton(
- stringResource(R.string.get_dialog_use_saved_passkey_for),
- onMoreOptionSelected
- )
- }
- } else null,
- rightButton = if (activeEntry != null) { // Only one sign-in options exist
- {
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- } else null,
- )
+ item {
+ CtaButtonRow(
+ leftButton = if (totalEntriesCount > 1) {
+ {
+ ActionButton(
+ stringResource(R.string.get_dialog_use_saved_passkey_for),
+ onMoreOptionSelected
+ )
+ }
+ } else null,
+ rightButton = if (activeEntry != null) { // Only one sign-in options exist
+ {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ }
+ } else null,
+ )
+ }
}
}
@@ -252,47 +264,45 @@
onNavigationIconClicked = if (isNoAccount) onCancel else onBackButtonClicked,
)
}) {
- LazyColumn {
- // For username
- items(sortedUserNameToCredentialEntryList) { item ->
- PerUserNameCredentials(
- perUserNameCredentialEntryList = item,
+ // For username
+ items(sortedUserNameToCredentialEntryList) { item ->
+ PerUserNameCredentials(
+ perUserNameCredentialEntryList = item,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ // Locked password manager
+ if (authenticationEntryList.isNotEmpty()) {
+ item {
+ LockedCredentials(
+ authenticationEntryList = authenticationEntryList,
onEntrySelected = onEntrySelected,
)
}
- // Locked password manager
- if (authenticationEntryList.isNotEmpty()) {
- item {
- LockedCredentials(
- authenticationEntryList = authenticationEntryList,
- onEntrySelected = onEntrySelected,
- )
- }
- }
- // From another device
- val remoteEntry = providerDisplayInfo.remoteEntry
- if (remoteEntry != null) {
- item {
- RemoteEntryCard(
- remoteEntry = remoteEntry,
- onEntrySelected = onEntrySelected,
- )
- }
- }
+ }
+ // From another device
+ val remoteEntry = providerDisplayInfo.remoteEntry
+ if (remoteEntry != null) {
item {
- Divider(
- thickness = 1.dp,
- color = Color.LightGray,
- modifier = Modifier.padding(top = 16.dp)
+ RemoteEntryCard(
+ remoteEntry = remoteEntry,
+ onEntrySelected = onEntrySelected,
)
}
- // Manage sign-ins (action chips)
- item {
- ActionChips(
- providerInfoList = providerInfoList,
- onEntrySelected = onEntrySelected
- )
- }
+ }
+ item {
+ Divider(
+ thickness = 1.dp,
+ color = Color.LightGray,
+ modifier = Modifier.padding(top = 16.dp)
+ )
+ }
+ // Manage sign-ins (action chips)
+ item {
+ ActionChips(
+ providerInfoList = providerInfoList,
+ onEntrySelected = onEntrySelected
+ )
}
}
}
@@ -337,7 +347,7 @@
) {
Entry(
onClick = { onEntrySelected(remoteEntry) },
- iconPainter = painterResource(R.drawable.ic_other_devices),
+ iconImageVector = Icons.Outlined.QrCodeScanner,
entryHeadlineText = stringResource(
R.string.get_dialog_option_headline_use_a_different_device
),
@@ -398,7 +408,7 @@
iconImageBitmap = credentialEntryInfo.icon?.toBitmap()?.asImageBitmap(),
// Fall back to iconPainter if iconImageBitmap isn't available
iconPainter =
- if (credentialEntryInfo.icon == null) painterResource(R.drawable.ic_other_sign_in)
+ if (credentialEntryInfo.icon == null) painterResource(R.drawable.ic_other_sign_in_24)
else null,
entryHeadlineText = credentialEntryInfo.userName,
entrySecondLineText = if (
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index af20a4b..750c156 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -70,7 +70,7 @@
"src/**/*.kt",
],
- min_sdk_version: "29",
+ min_sdk_version: "30",
}
diff --git a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
index 940f5c9..78a7408 100644
--- a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
+++ b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
@@ -1,17 +1,12 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
- <option name="PACKAGES_TO_USE_STAR_IMPORTS">
- <value />
- </option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
- <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
- <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<XML>
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle
index 42af999..643af75 100644
--- a/packages/SettingsLib/Spa/build.gradle
+++ b/packages/SettingsLib/Spa/build.gradle
@@ -24,7 +24,7 @@
}
}
plugins {
- id 'com.android.application' version '7.3.1' apply false
- id 'com.android.library' version '7.3.1' apply false
+ id 'com.android.application' version '8.0.0-beta01' apply false
+ id 'com.android.library' version '8.0.0-beta01' apply false
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
}
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
index bd7e7ff..53b24b0 100644
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
@@ -16,7 +16,7 @@
#Thu Jul 14 10:36:06 CST 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/packages/SettingsLib/Spa/spa/build.gradle b/packages/SettingsLib/Spa/spa/build.gradle
index 640aa01..4563b7d 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle
+++ b/packages/SettingsLib/Spa/spa/build.gradle
@@ -48,11 +48,11 @@
}
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = '11'
+ jvmTarget = '17'
freeCompilerArgs = ["-Xjvm-default=all"]
}
buildFeatures {
diff --git a/packages/SettingsLib/Spa/testutils/build.gradle b/packages/SettingsLib/Spa/testutils/build.gradle
index 536829e..e7f7db2 100644
--- a/packages/SettingsLib/Spa/testutils/build.gradle
+++ b/packages/SettingsLib/Spa/testutils/build.gradle
@@ -38,11 +38,11 @@
}
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = '11'
+ jvmTarget = '17'
freeCompilerArgs = ["-Xjvm-default=all"]
}
buildFeatures {
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 1907b3e..28f7c50 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Het gefiltreer geaktiveer"</item>
<item msgid="2779123106632690576">"Geaktiveer"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Opskrifte is gefiltreer"</item>
- <item msgid="4818549483446395865">"A2DP-mediapakkette is gefiltreer"</item>
- <item msgid="8207123990453243311">"RFCOMM-kanaal is gefiltreer"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Gedeaktiveer"</item>
- <item msgid="5884245882825346396">"Wonder"</item>
- <item msgid="6569400572915342949">"Opskrif"</item>
- <item msgid="1239386221416967664">"Volledige filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (verstek)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 31f50e8..3de581e 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en onthounotas"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Laat toe dat wekkers en onthounotas gestel word"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie program toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die program op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie program geskeduleer is, nie werk nie."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie app toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die app op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie app geskeduleer is, nie werk nie."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index ad0f1ed..c423d3c 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ማጣሪያን አንቃ"</item>
<item msgid="2779123106632690576">"ነቅቷል"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ራስጌዎች ተጣርተዋል"</item>
- <item msgid="4818549483446395865">"የA2DP ሚዲያ ፓኬቶች ተጣርተዋል"</item>
- <item msgid="8207123990453243311">"የRFCOMM ሰርጥ ተጣርቷል"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"ተሰናክሏል"</item>
- <item msgid="5884245882825346396">"ማጂክ"</item>
- <item msgid="6569400572915342949">"የራስጌ ጽሑፍ"</item>
- <item msgid="1239386221416967664">"ሙሉ ማጣሪያ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ነባሪ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index cede18e..cf46a8f 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"تمّ تفعيل التصفية"</item>
<item msgid="2779123106632690576">"مفعّل"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"العناوين المفلترة"</item>
- <item msgid="4818549483446395865">"حُزم وسائط A2DP مفلترة"</item>
- <item msgid="8207123990453243311">"قناة بروتوكول RFCOMM مفلترة"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"حُزم البيانات غير المفعّلة"</item>
- <item msgid="5884245882825346396">"سِحري"</item>
- <item msgid="6569400572915342949">"العنوان"</item>
- <item msgid="1239386221416967664">"فلترة كاملة"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (تلقائي)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index c52d27e2..284ca12 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"সক্ষম কৰাবিলাক ফিল্টাৰ কৰা হৈছে"</item>
<item msgid="2779123106632690576">"সক্ষম কৰা আছে"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"হেডাৰ ফিল্টাৰ কৰা হৈছে"</item>
- <item msgid="4818549483446395865">"A2DP মিডিয়াৰ পেকেট ফিল্টাৰ কৰা হৈছে"</item>
- <item msgid="8207123990453243311">"RFCOMM চেনেল ফিল্টাৰ কৰা হৈছে"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"অক্ষম কৰা আছে"</item>
- <item msgid="5884245882825346396">"যাদু"</item>
- <item msgid="6569400572915342949">"হেডাৰ"</item>
- <item msgid="1239386221416967664">"সম্পূৰ্ণ ফিল্টাৰ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ডিফ’ল্ট)"</item>
<item msgid="1637054408779685086">"AVRCP ১.৩"</item>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 9605c51..ff0054b 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrləmə aktivdir"</item>
<item msgid="2779123106632690576">"Aktivdir"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Başlıqlar Filtrlənib"</item>
- <item msgid="4818549483446395865">"A2DP Media Paketləri Filtrlənib"</item>
- <item msgid="8207123990453243311">"RFCOMM Kanalı Filtrlənib"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Deaktiv"</item>
- <item msgid="5884245882825346396">"Sehr"</item>
- <item msgid="6569400572915342949">"Başlıq"</item>
- <item msgid="1239386221416967664">"Tam Filtr"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Defolt)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 618748b..32071e5 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogućeno"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
- <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
- <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Onemogućeno"</item>
- <item msgid="5884245882825346396">"Magija"</item>
- <item msgid="6569400572915342949">"Zaglavlje"</item>
- <item msgid="1239386221416967664">"Potpuni filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (podrazumevano)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 117f0b4..a60d354 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Уключана з фільтрацыяй"</item>
<item msgid="2779123106632690576">"Уключана"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Адфільтраваны загалоўкі"</item>
- <item msgid="4818549483446395865">"Адфільтраваны пакеты мультымедыя A2DP"</item>
- <item msgid="8207123990453243311">"Адфільтраваны канал RFCOMM"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Адключана"</item>
- <item msgid="5884245882825346396">"Спецыяльная фраза"</item>
- <item msgid="6569400572915342949">"Загаловак"</item>
- <item msgid="1239386221416967664">"Поўная фільтрацыя"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (стандартная)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index cf643c8..d778ca2 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Филтрирането е активирано"</item>
<item msgid="2779123106632690576">"Активирано"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Заглавките са филтрирани"</item>
- <item msgid="4818549483446395865">"Мултимедийните пакети A2DP са филтрирани"</item>
- <item msgid="8207123990453243311">"Каналът RFCOMM е филтриран"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Деактивирано"</item>
- <item msgid="5884245882825346396">"Магия"</item>
- <item msgid="6569400572915342949">"Заглавка"</item>
- <item msgid="1239386221416967664">"Пълен филтър"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (основно)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 1a7652d..dbb738c 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ফিল্টার করা চালু আছে"</item>
<item msgid="2779123106632690576">"চালু করা আছে"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"হেডার ফিল্টার করা হয়েছে"</item>
- <item msgid="4818549483446395865">"A2DP মিডিয়া প্যাকেট ফিল্টার করা হয়েছে"</item>
- <item msgid="8207123990453243311">"RFCOMM চ্যানেল ফিল্টার করা হয়েছে"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"বন্ধ করা আছে"</item>
- <item msgid="5884245882825346396">"ম্যাজিক"</item>
- <item msgid="6569400572915342949">"হেডার"</item>
- <item msgid="1239386221416967664">"সম্পূর্ণ ফিল্টার"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ডিফল্ট)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 2ab1b79..740e704 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogućeno"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
- <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
- <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Onemogućeno"</item>
- <item msgid="5884245882825346396">"Magija"</item>
- <item msgid="6569400572915342949">"Zaglavlje"</item>
- <item msgid="1239386221416967664">"Potpuni filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e8cabfa..1aa8ff3 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dozvoli postavljanje alarma i podsjetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu koje je ova aplikacija zakazala neće funkcionirati."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu, a koje je ova aplikacija zakazala, neće funkcionirati."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 00a126c..4e437ba 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Activat amb filtres"</item>
<item msgid="2779123106632690576">"Activat"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Capçaleres filtrades"</item>
- <item msgid="4818549483446395865">"Paquets multimèdia A2DP filtrats"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrat"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Desactivat"</item>
- <item msgid="5884245882825346396">"Màgia"</item>
- <item msgid="6569400572915342949">"Capçalera"</item>
- <item msgid="1239386221416967664">"Filtre complet"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminada)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 83b32d4..f14befd 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes i recordatoris"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permet la configuració d\'alarmes i recordatoris"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions a una hora determinada. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index a4bd21f..e1a5aef 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Povolit filtrované"</item>
<item msgid="2779123106632690576">"Zapnuto"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Záhlaví filtrována"</item>
- <item msgid="4818549483446395865">"Mediální balíčky A2DP filtrovány"</item>
- <item msgid="8207123990453243311">"Kanál RFCOMM filtrován"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Zakázáno"</item>
- <item msgid="5884245882825346396">"Komplexní hodnocení"</item>
- <item msgid="6569400572915342949">"Záhlaví"</item>
- <item msgid="1239386221416967664">"Úplný filtr"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (výchozí)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 37da365..03cab20 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtreret er aktiveret"</item>
<item msgid="2779123106632690576">"Aktiveret"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Overskrifter filtreret"</item>
- <item msgid="4818549483446395865">"A2DP-mediepakker filtreret"</item>
- <item msgid="8207123990453243311">"RFCOMM-kanal filtreret"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Deaktiveret"</item>
- <item msgid="5884245882825346396">"Magi"</item>
- <item msgid="6569400572915342949">"Overskrift"</item>
- <item msgid="1239386221416967664">"Fuldt filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 2241666..c5dcc10 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filter aktiviert"</item>
<item msgid="2779123106632690576">"Aktiviert"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Header gefiltert"</item>
- <item msgid="4818549483446395865">"A2DP-Medienpakete gefiltert"</item>
- <item msgid="8207123990453243311">"RFCOMM-Kanal gefiltert"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Deaktiviert"</item>
- <item msgid="5884245882825346396">"Magie"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Vollständig gefiltert"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 1a824c1..6486b3d 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Ενεργοποιήθηκε το φιλτράρισμα"</item>
<item msgid="2779123106632690576">"Ενεργοποιήθηκε"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Φιλτραρισμένες κεφαλίδες"</item>
- <item msgid="4818549483446395865">"Φιλτραρισμένα πακέτα μέσων A2DP"</item>
- <item msgid="8207123990453243311">"Φιλτραρισμένο κανάλι RFCOMM"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Ανενεργό"</item>
- <item msgid="5884245882825346396">"Μαγεία"</item>
- <item msgid="6569400572915342949">"Κεφαλίδα"</item>
- <item msgid="1239386221416967664">"Πλήρες φίλτρο"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Προεπιλογή)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Enabled Filtered"</item>
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers filtered"</item>
- <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 0af8b4e..184d210 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -64,15 +64,15 @@
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
<string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers Filtered"</item>
- <item msgid="4818549483446395865">"A2DP Media Packets Filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM Channel Filtered"</item>
+ <item msgid="195768089203590086">"Leave only ACL headers"</item>
+ <item msgid="2776218217644557831">"Filter A2DP media packets"</item>
+ <item msgid="8163235976612675092">"Filter RFCOMM channel"</item>
</string-array>
<string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full Filter"</item>
+ <item msgid="3961868665260627524">"Disable"</item>
+ <item msgid="2505973306504851132">"Fill with string of characters"</item>
+ <item msgid="5883011000629613855">"Leave only header"</item>
+ <item msgid="1051534112762023603">"Fully remove"</item>
</string-array>
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Enabled Filtered"</item>
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers filtered"</item>
- <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Enabled Filtered"</item>
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers filtered"</item>
- <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index 30c9a49..dec70f4 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -64,15 +64,15 @@
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
<string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers Filtered"</item>
- <item msgid="4818549483446395865">"A2DP Media Packets Filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM Channel Filtered"</item>
+ <item msgid="195768089203590086">"Leave only ACL headers"</item>
+ <item msgid="2776218217644557831">"Filter A2DP media packets"</item>
+ <item msgid="8163235976612675092">"Filter RFCOMM channel"</item>
</string-array>
<string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full Filter"</item>
+ <item msgid="3961868665260627524">"Disable"</item>
+ <item msgid="2505973306504851132">"Fill with string of characters"</item>
+ <item msgid="5883011000629613855">"Leave only header"</item>
+ <item msgid="1051534112762023603">"Fully remove"</item>
</string-array>
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index e2a36c6..771690d 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrado habilitado"</item>
<item msgid="2779123106632690576">"Habilitado"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Títulos filtrados"</item>
- <item msgid="4818549483446395865">"Paquetes de medios A2DP filtrados"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Inhabilitada"</item>
- <item msgid="5884245882825346396">"Automático"</item>
- <item msgid="6569400572915342949">"Título"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index b5e035c..e07f9dc 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Habilitado con filtros"</item>
<item msgid="2779123106632690576">"Habilitado"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Encabezados filtrados"</item>
- <item msgid="4818549483446395865">"Paquetes de medios A2DP filtrados"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Inhabilitado"</item>
- <item msgid="5884245882825346396">"Mágico"</item>
- <item msgid="6569400572915342949">"Encabezado"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index d910a0e..34448a7 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Luba filtreeritud"</item>
<item msgid="2779123106632690576">"Lubatud"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtreeritud päised"</item>
- <item msgid="4818549483446395865">"Filtreeritud A2DP meediapaketid"</item>
- <item msgid="8207123990453243311">"Filtreeritud RFCOMM-kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Keelatud"</item>
- <item msgid="5884245882825346396">"Maagiline"</item>
- <item msgid="6569400572915342949">"Päis"</item>
- <item msgid="1239386221416967664">"Täielik filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (vaikeseade)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 2d3575b..eb678ff 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Gaituta baina iragazita"</item>
<item msgid="2779123106632690576">"Gaituta"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Goiburuan iragazita"</item>
- <item msgid="4818549483446395865">"A2DP multimedia-paketeak iragazita"</item>
- <item msgid="8207123990453243311">"RFCOMM kanala iragazita"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Desgaituta"</item>
- <item msgid="5884245882825346396">"Magia"</item>
- <item msgid="6569400572915342949">"Goiburua"</item>
- <item msgid="1239386221416967664">"Iragazki osoa"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (lehenetsia)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 82e0eea..02ab192 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmak eta abisuak"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Eman alarmak eta abisuak ezartzeko baimena"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nEz baduzu ematen baimen hori, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nBaimen hori ematen ez baduzu, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index b983bcc..2d9be31 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"فیلترشده فعال شده است"</item>
<item msgid="2779123106632690576">"فعال"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"سرصفحهها فیلتر شد"</item>
- <item msgid="4818549483446395865">"بستههای رسانه A2DP فیلتر شد"</item>
- <item msgid="8207123990453243311">"کانال RFCOMM فیلتر شد"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"غیرفعال"</item>
- <item msgid="5884245882825346396">"جادویی"</item>
- <item msgid="6569400572915342949">"سرصفحه"</item>
- <item msgid="1239386221416967664">"فیلتر کامل"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP نسخه ۱.۵ (پیشفرض)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 9e3bcd2..d6f002f 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Suodatus käytössä"</item>
<item msgid="2779123106632690576">"Päällä"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Otsikot suodatettu"</item>
- <item msgid="4818549483446395865">"A2DP-mediapaketit suodatettu"</item>
- <item msgid="8207123990453243311">"RFCOMM-kanava suodatettu"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Ei käytössä"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Otsikko"</item>
- <item msgid="1239386221416967664">"Täysi suodatus"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (oletus)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 86066b6..6657aa1 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtres activés"</item>
<item msgid="2779123106632690576">"Activé"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"En-têtes filtrés"</item>
- <item msgid="4818549483446395865">"Paquets multimédias A2DP filtrés"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtré"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Désactivé"</item>
- <item msgid="5884245882825346396">"Magie"</item>
- <item msgid="6569400572915342949">"En-tête"</item>
- <item msgid="1239386221416967664">"Filtre intégral"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 5f31ff5..869d88a 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Activé et filtré"</item>
<item msgid="2779123106632690576">"Activé"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"En-têtes filtrés"</item>
- <item msgid="4818549483446395865">"Paquets multimédias A2DP filtrés"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtré"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Désactivé"</item>
- <item msgid="5884245882825346396">"Magie"</item>
- <item msgid="6569400572915342949">"En-tête"</item>
- <item msgid="1239386221416967664">"Filtre complet"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 665851d..3cd7b4b 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Está activado o filtrado"</item>
<item msgid="2779123106632690576">"Activada"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Cabeceiras filtradas"</item>
- <item msgid="4818549483446395865">"A2DP Media Packets filtrados"</item>
- <item msgid="8207123990453243311">"Canle RFCOMM filtrada"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Desactivado"</item>
- <item msgid="5884245882825346396">"Maxia"</item>
- <item msgid="6569400572915342949">"Cabeceira"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index e373952..f559b80 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ફિલ્ટર કરેલ ચાલુ છે"</item>
<item msgid="2779123106632690576">"ચાલુ છે"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ફિલ્ટર કરેલા હેડર"</item>
- <item msgid="4818549483446395865">"ફિલ્ટર કરેલા A2DP મીડિયા પૅકેટ"</item>
- <item msgid="8207123990453243311">"ફિલ્ટર કરેલી RFCOMM ચૅનલ"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"બંધ કર્યું"</item>
- <item msgid="5884245882825346396">"જાદુ"</item>
- <item msgid="6569400572915342949">"હેડર"</item>
- <item msgid="1239386221416967664">"સંપૂર્ણ ફિલ્ટર"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ડિફૉલ્ટ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 356a13c..be88620 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"चालू और फ़िल्टर किया गया"</item>
<item msgid="2779123106632690576">"चालू है"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"हेडर फ़िल्टर किए गए"</item>
- <item msgid="4818549483446395865">"A2DP मीडिया पैकेट फ़िल्टर किए गए"</item>
- <item msgid="8207123990453243311">"RFCOMM चैनल फ़िल्टर किए गए"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"बंद है"</item>
- <item msgid="5884245882825346396">"मैजिक"</item>
- <item msgid="6569400572915342949">"हेडर"</item>
- <item msgid="1239386221416967664">"सभी फ़िल्टर"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (डिफ़ॉल्ट)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 812f8d2..5c73ebb 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogućeno"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
- <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
- <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Onemogućeno"</item>
- <item msgid="5884245882825346396">"Čarolija"</item>
- <item msgid="6569400572915342949">"Zaglavlje"</item>
- <item msgid="1239386221416967664">"Potpuni filtar"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 9c842f9..500b9fd 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Szűrtek engedélyezve"</item>
<item msgid="2779123106632690576">"Engedélyezve"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Szűrt fejlécek"</item>
- <item msgid="4818549483446395865">"Szűrt A2DP-médiacsomagok"</item>
- <item msgid="8207123990453243311">"Szűrt RFCOMM-csatorna"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Kikapcsolva"</item>
- <item msgid="5884245882825346396">"Mágia"</item>
- <item msgid="6569400572915342949">"Fejléc"</item>
- <item msgid="1239386221416967664">"Teljes szűrő"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (alapértelmezett)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 59351c4..6fd6893 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Միացված է զտիչներով"</item>
<item msgid="2779123106632690576">"Միացված է"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Զտված էջագլուխներ"</item>
- <item msgid="4818549483446395865">"Զտված A2DP մուլտիմեդիա փաթեթներ"</item>
- <item msgid="8207123990453243311">"Զտված RFCOMM կապուղի"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Անջատված է"</item>
- <item msgid="5884245882825346396">"Կախարդանք"</item>
- <item msgid="6569400572915342949">"Էջագլուխ"</item>
- <item msgid="1239386221416967664">"Ամբողջական զտիչ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (կանխադրված)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 06e24b9..8257d0e 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Diaktifkan Difilter"</item>
<item msgid="2779123106632690576">"Diaktifkan"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Header Difilter"</item>
- <item msgid="4818549483446395865">"Paket Media A2DP Difilter"</item>
- <item msgid="8207123990453243311">"Saluran RFCOMM Difilter"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Nonaktif"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Filter Lengkap"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index a87e760..1b114ee 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Kveikt á síuðu"</item>
<item msgid="2779123106632690576">"Kveikt"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Síaðar fyrirsagnir"</item>
- <item msgid="4818549483446395865">"Síaðir A2DP-efnispakkar"</item>
- <item msgid="8207123990453243311">"Síuð RFCOMM-rás"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Slökkt"</item>
- <item msgid="5884245882825346396">"Töfrar"</item>
- <item msgid="6569400572915342949">"Haus"</item>
- <item msgid="1239386221416967664">"Heildarsía"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (sjálfgefið)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 18923b6..50eca93 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtro attivo"</item>
<item msgid="2779123106632690576">"Attiva"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Intestazioni filtrate"</item>
- <item msgid="4818549483446395865">"Pacchetti multimediali A2DP filtrati"</item>
- <item msgid="8207123990453243311">"Canale RFCOMM filtrato"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disattivato"</item>
- <item msgid="5884245882825346396">"Magia"</item>
- <item msgid="6569400572915342949">"Intestazione"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (versione predefinita)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 8e76f2e..02b7751 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"המסננים המופעלים"</item>
<item msgid="2779123106632690576">"מופעל"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"כותרות לאחר סינון"</item>
- <item msgid="4818549483446395865">"מנות מדיה A2DP לאחר סינון"</item>
- <item msgid="8207123990453243311">"ערוצי RFCOMM לאחר סינון"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"בהשבתה"</item>
- <item msgid="5884245882825346396">"קסם"</item>
- <item msgid="6569400572915342949">"כותרת"</item>
- <item msgid="1239386221416967664">"סינון מלא"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ברירת המחדל)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 47517fe..869fd997 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"有効(フィルタ済み)"</item>
<item msgid="2779123106632690576">"有効"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ヘッダーのフィルタ"</item>
- <item msgid="4818549483446395865">"A2DP メディア パケットのフィルタ"</item>
- <item msgid="8207123990453243311">"RFCOMM チャネルのフィルタ"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"無効"</item>
- <item msgid="5884245882825346396">"マジック"</item>
- <item msgid="6569400572915342949">"ヘッダー"</item>
- <item msgid="1239386221416967664">"フルフィルタ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5(デフォルト)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index eceaac7..71a283c 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"გაფილტრულის ჩართვა"</item>
<item msgid="2779123106632690576">"ჩართულია"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"გაფილტრული სათაურები"</item>
- <item msgid="4818549483446395865">"გაფილტრული A2DP მედია პაკეტები"</item>
- <item msgid="8207123990453243311">"გაფილტრული RFCOMM არხი"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"გათიშული"</item>
- <item msgid="5884245882825346396">"მაგია"</item>
- <item msgid="6569400572915342949">"სათაური"</item>
- <item msgid="1239386221416967664">"სრული ფილტრი"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ნაგულისხმევი)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 517b116..ab5e107 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Сүзгіленгендері қосулы"</item>
<item msgid="2779123106632690576">"Қосулы"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Сүзілген тақырыптар"</item>
- <item msgid="4818549483446395865">"Сүзілген A2DP медиапакеттері"</item>
- <item msgid="8207123990453243311">"Сүзілген RFCOMM арнасы"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Өшірулі"</item>
- <item msgid="5884245882825346396">"Сиқыр"</item>
- <item msgid="6569400572915342949">"Тақырып"</item>
- <item msgid="1239386221416967664">"Толық сүзгі"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (әдепкі)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index db99329..bfc9834 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"បានបើកការត្រង"</item>
<item msgid="2779123106632690576">"បានបើក"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"បានត្រងក្បាលទំព័រ"</item>
- <item msgid="4818549483446395865">"បានត្រងកញ្ចប់មេឌៀ A2DP"</item>
- <item msgid="8207123990453243311">"បានត្រងបណ្ដាញ RFCOMM"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"បានបិទ"</item>
- <item msgid="5884245882825346396">"វេទមន្ត"</item>
- <item msgid="6569400572915342949">"ក្បាលទំព័រ"</item>
- <item msgid="1239386221416967664">"តម្រងពេញ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (លំនាំដើម)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 2bf4ef0..61e2791 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ಫಿಲ್ಟರ್ ಮಾಡುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
<item msgid="2779123106632690576">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ಶಿರೋಲೇಖಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಲಾಗಿದೆ"</item>
- <item msgid="4818549483446395865">"A2DP ಮೀಡಿಯಾ ಪ್ಯಾಕೆಟ್ಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಲಾಗಿದೆ"</item>
- <item msgid="8207123990453243311">"RFCOMM ಚಾನಲ್ ಫಿಲ್ಟರ್ ಮಾಡಲಾಗಿದೆ"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
- <item msgid="5884245882825346396">"ಮ್ಯಾಜಿಕ್"</item>
- <item msgid="6569400572915342949">"ಶಿರೋಲೇಖ"</item>
- <item msgid="1239386221416967664">"ಸಂಪೂರ್ಣ ಫಿಲ್ಟರ್"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ಡೀಫಾಲ್ಟ್)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 1a1469f..b4a035a 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"필터링 사용 설정됨"</item>
<item msgid="2779123106632690576">"사용 설정됨"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"헤더 필터링됨"</item>
- <item msgid="4818549483446395865">"A2DP 미디어 패킷 필터링됨"</item>
- <item msgid="8207123990453243311">"RFCOMM 채널 필터링됨"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"사용 안함"</item>
- <item msgid="5884245882825346396">"매직"</item>
- <item msgid="6569400572915342949">"헤더"</item>
- <item msgid="1239386221416967664">"전체 필터"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5(기본값)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index f59d4d4..657e63e 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Чыпкалар иштетилди"</item>
<item msgid="2779123106632690576">"Иштетилди"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Жогорку колонтитулдар чыпкаланды"</item>
- <item msgid="4818549483446395865">"A2DP медиа топтомдор чыпкаланды"</item>
- <item msgid="8207123990453243311">"RFCOMM каналы чыпкаланды"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Өчүрүлдү"</item>
- <item msgid="5884245882825346396">"Сыйкырдуу"</item>
- <item msgid="6569400572915342949">"Жогорку колонтитул"</item>
- <item msgid="1239386221416967664">"Толук чыпка"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Демейки)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 4981273..11688d4 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ເປີດການກັ່ນຕອງແລ້ວ"</item>
<item msgid="2779123106632690576">"ເປີດໃຊ້ແລ້ວ"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ສ່ວນຫົວຖືກກັ່ນຕອງ"</item>
- <item msgid="4818549483446395865">"ແພັກເກດສື່ A2DP ຖືກກັ່ນຕອງ"</item>
- <item msgid="8207123990453243311">"ຊ່ອງ RFCOMM ຖືກກັ່ນຕອງ"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"ປິດການນຳໃຊ້ແລ້ວ"</item>
- <item msgid="5884245882825346396">"ເວດມົນ"</item>
- <item msgid="6569400572915342949">"ສ່ວນຫົວ"</item>
- <item msgid="1239386221416967664">"ການກັ່ນຕອງແບບເຕັມ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ຄ່າເລີ່ມຕົ້ນ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 15e65e8..6718660 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Įgalinta filtruota"</item>
<item msgid="2779123106632690576">"Įgalinta"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Antraštės išfiltruotos"</item>
- <item msgid="4818549483446395865">"A2DP medijos paketai išfiltruoti"</item>
- <item msgid="8207123990453243311">"RFCOMM kanalas išfiltruotas"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Išjungta"</item>
- <item msgid="5884245882825346396">"Magiškoji eilutė"</item>
- <item msgid="6569400572915342949">"Antraštė"</item>
- <item msgid="1239386221416967664">"Visi filtrai"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (numatytoji)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 47531a0..3e1869a 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Iespējot filtrētos"</item>
<item msgid="2779123106632690576">"Iespējots"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrētas galvenes"</item>
- <item msgid="4818549483446395865">"Filtrētas A2DP multivides paketes"</item>
- <item msgid="8207123990453243311">"Filtrēts RFCOMM kanāls"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Atspējots"</item>
- <item msgid="5884245882825346396">"Pielāgotās virknes"</item>
- <item msgid="6569400572915342949">"Galvene"</item>
- <item msgid="1239386221416967664">"Visi filtri"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (noklusējums)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 9d5a5e1..ebf387b 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Овозможено е филтрирано"</item>
<item msgid="2779123106632690576">"Овозможено"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Насловите се филтрирани"</item>
- <item msgid="4818549483446395865">"A2DP аудиовизуелните пакети се филтрирани"</item>
- <item msgid="8207123990453243311">"RFCOMM-каналот е филтриран"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Оневозможено"</item>
- <item msgid="5884245882825346396">"Магија"</item>
- <item msgid="6569400572915342949">"Заглавие"</item>
- <item msgid="1239386221416967664">"Целосен филтер"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Стандардна)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index f28be85..30adb57 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ഫിൽട്ടറിംഗ് പ്രവർത്തനക്ഷമമാക്കി"</item>
<item msgid="2779123106632690576">"പ്രവർത്തനക്ഷമമാക്കി"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ഹെഡ്ഡറുകൾ ഫിൽട്ടർ ചെയ്തു"</item>
- <item msgid="4818549483446395865">"A2DP മീഡിയാ പാക്കറ്റകൾ ഫിൽട്ടർ ചെയ്തു"</item>
- <item msgid="8207123990453243311">"RFCOMM ചാനൽ ഫിൽട്ടർ ചെയ്തു"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"പ്രവർത്തനരഹിതമാക്കി"</item>
- <item msgid="5884245882825346396">"മാജിക്"</item>
- <item msgid="6569400572915342949">"ഹെഡ്ഡർ"</item>
- <item msgid="1239386221416967664">"പൂർണ്ണ ഫിൽട്ടർ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ഡിഫോൾട്ട്)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index d3c344e..d03fcd6 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Идэвхжүүлсэн Шүүсэн"</item>
<item msgid="2779123106632690576">"Идэвхжүүлсэн"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Толгой хэсгийг шүүсэн"</item>
- <item msgid="4818549483446395865">"A2DP Медиа пакетыг шүүсэн"</item>
- <item msgid="8207123990453243311">"RFCOMM сувгийг шүүсэн"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Идэвхгүй болгосон"</item>
- <item msgid="5884245882825346396">"Ид шид"</item>
- <item msgid="6569400572915342949">"Толгой хэсэг"</item>
- <item msgid="1239386221416967664">"Бүтэн шүүлтүүр"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Өгөгдмөл)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 093e36b..68eff75 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"फिल्टर केलेले सुरू केले"</item>
<item msgid="2779123106632690576">"सुरू केले"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"फिल्टर केलेले हेडर"</item>
- <item msgid="4818549483446395865">"फिल्टर केलेली A2DP मीडिया पॅकेट"</item>
- <item msgid="8207123990453243311">"फिल्टर केलेली RFCOMM चॅनल"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"बंद केले"</item>
- <item msgid="5884245882825346396">"मॅजिक"</item>
- <item msgid="6569400572915342949">"हेडर"</item>
- <item msgid="1239386221416967664">"पूर्ण फिल्टर"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (डीफॉल्ट)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 1daa579..efdd879 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Didayakan Ditapis"</item>
<item msgid="2779123106632690576">"Didayakan"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Pengepala Ditapis"</item>
- <item msgid="4818549483446395865">"Paket Media A2DP Ditapis"</item>
- <item msgid="8207123990453243311">"Saluran RFCOMM Ditapis"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Dilumpuhkan"</item>
- <item msgid="5884245882825346396">"Magik"</item>
- <item msgid="6569400572915342949">"Pengepala"</item>
- <item msgid="1239386221416967664">"Penapis Penuh"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Lalai)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index dbca299..4d0b792 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"စစ်ထုတ်ထားသည်များကို ဖွင့်ထားသည်"</item>
<item msgid="2779123106632690576">"ဖွင့်ထားသည်"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"စစ်ထုတ်ထားသော ခေါင်းစီးများ"</item>
- <item msgid="4818549483446395865">"စစ်ထုတ်ထားသော A2DP မီဒီယာအတွဲများ"</item>
- <item msgid="8207123990453243311">"စစ်ထုတ်ထားသော RFCOMM ချန်နယ်"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"ပိတ်ထားသည်"</item>
- <item msgid="5884245882825346396">"ပဉ္စလက်"</item>
- <item msgid="6569400572915342949">"ခေါင်းစီး"</item>
- <item msgid="1239386221416967664">"စစ်ထုတ်မှုအပြည့်"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (မူလ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 35c4cdd..9293bdad 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrering er slått på"</item>
<item msgid="2779123106632690576">"Slått på"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrert topptekst"</item>
- <item msgid="4818549483446395865">"Filtrerte A2DP-mediepakker"</item>
- <item msgid="8207123990453243311">"Filtrert RFCOMM-kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Slått av"</item>
- <item msgid="5884245882825346396">"Magi"</item>
- <item msgid="6569400572915342949">"Topptekst"</item>
- <item msgid="1239386221416967664">"Fullt filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 76652cd..29a7c60 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"फिल्टर सक्षम पारियो"</item>
<item msgid="2779123106632690576">"सक्षम पारिएको छ"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"हेडरहरू फिल्टर गरिए"</item>
- <item msgid="4818549483446395865">"A2DP मिडिया प्याकेटहरू फिल्टर गरिए"</item>
- <item msgid="8207123990453243311">"RFCOMM च्यानल फिल्टर गरियो"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"अफ गरियो"</item>
- <item msgid="5884245882825346396">"म्याजिक"</item>
- <item msgid="6569400572915342949">"हेडर"</item>
- <item msgid="1239386221416967664">"फुल फिल्टर"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP १.५ (डिफल्ट)"</item>
<item msgid="1637054408779685086">"AVRCP १.३"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index ae7e8b3..831ed2f 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -520,7 +520,7 @@
<string name="okay" msgid="949938843324579502">"ठिक छ"</string>
<string name="done" msgid="381184316122520313">"सम्पन्न भयो"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म र रिमाइन्डरहरू"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्न दिइयोस्"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्ने अनुमति दिनुहोस्"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म तथा रिमाइन्डर"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन बनाउने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा चल्छ र धेरै ब्याट्री खपत हुन्छ।\n\nयो अनुमति दिइएको छैन भने सेट गरिएका अलार्म बज्दैनन् र यो एपले तय गरेका गतिविधि चल्दैनन्।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index 2ecfbd8..460302c 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Gefilterd staat aan"</item>
<item msgid="2779123106632690576">"Aangezet"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers gefilterd"</item>
- <item msgid="4818549483446395865">"A2DP-mediapakketten gefilterd"</item>
- <item msgid="8207123990453243311">"RFCOMM-kanaal gefilterd"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Uitgezet"</item>
- <item msgid="5884245882825346396">"Magie"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Volledig filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standaard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 5f48344..439bd72 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ଫିଲ୍ଟର୍କୁ ସକ୍ଷମ କରାଯାଇଛି"</item>
<item msgid="2779123106632690576">"ସକ୍ଷମ କରାଯାଇଛି"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ହେଡରଗୁଡ଼ିକୁ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
- <item msgid="4818549483446395865">"A2DP ମିଡିଆ ପେକେଟ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
- <item msgid="8207123990453243311">"RFCOMM ଚେନେଲ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"ଅକ୍ଷମ କରାଯାଇଛି"</item>
- <item msgid="5884245882825346396">"ମେଜିକ"</item>
- <item msgid="6569400572915342949">"ହେଡର"</item>
- <item msgid="1239386221416967664">"ସମ୍ପୂର୍ଣ୍ଣ ଫିଲ୍ଟର"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ଡିଫଲ୍ଟ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index d8b1c7e..f4bfcd1 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ਫਿਲਟਰ ਕੀਤਿਆਂ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</item>
<item msgid="2779123106632690576">"ਚਾਲੂ"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ਸਿਰਲੇਖ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
- <item msgid="4818549483446395865">"A2DP ਮੀਡੀਆ ਪੈਕੇਟ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
- <item msgid="8207123990453243311">"RFCOMM ਚੈਨਲ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"ਬੰਦ ਹੈ"</item>
- <item msgid="5884245882825346396">"ਜਾਦੂ"</item>
- <item msgid="6569400572915342949">"ਸਿਰਲੇਖ"</item>
- <item msgid="1239386221416967664">"ਸਭ ਫਿਲਟਰ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 9659acb..a305a65 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrowanie włączone"</item>
<item msgid="2779123106632690576">"Włączono"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Przefiltrowane nagłówki"</item>
- <item msgid="4818549483446395865">"Przefiltrowane pakiety multimediów A2DP"</item>
- <item msgid="8207123990453243311">"Przefiltrowany kanał RFCOMM"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Wyłączono"</item>
- <item msgid="5884245882825346396">"Magia"</item>
- <item msgid="6569400572915342949">"Nagłówek"</item>
- <item msgid="1239386221416967664">"Pełny filtr"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (domyślnie)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 84aa66a..ddff92c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmy i przypomnienia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwalaj na ustawianie alarmów i przypomnień"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwól na ustawianie alarmów i planowanie innych działań, w przypadku których czas jest istotny. Dzięki temu aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tych uprawnień, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwalaj tej aplikacji na ustawianie alarmów i planowanie działań, w przypadku których czas jest istotny. Aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tego uprawnienia, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 0bff6c7..eff0922 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtro ativado"</item>
<item msgid="2779123106632690576">"Ativado"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
- <item msgid="4818549483446395865">"Pacotes de mídia A2DP filtrados"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Desativado"</item>
- <item msgid="5884245882825346396">"Mágica"</item>
- <item msgid="6569400572915342949">"Cabeçalho"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 168207d..3a48c3d 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index b134be6..0553aac 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrado ativado"</item>
<item msgid="2779123106632690576">"Ativado"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
- <item msgid="4818549483446395865">"Pacotes de multimédia A2DP filtrados"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Desativado"</item>
- <item msgid="5884245882825346396">"Magia"</item>
- <item msgid="6569400572915342949">"Cabeçalho"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predefinição)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 5c2d4f2..499477e 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -520,7 +520,7 @@
<string name="okay" msgid="949938843324579502">"OK"</string>
<string name="done" msgid="381184316122520313">"Concluir"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir a definição de alarmes e lembretes"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que esta app defina alarmes e agende outras ações com base no tempo. Esta ação permite que a app seja executada em segundo plano, o que pode utilizar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, alarme, lembrete, relógio"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 0bff6c7..eff0922 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtro ativado"</item>
<item msgid="2779123106632690576">"Ativado"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
- <item msgid="4818549483446395865">"Pacotes de mídia A2DP filtrados"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Desativado"</item>
- <item msgid="5884245882825346396">"Mágica"</item>
- <item msgid="6569400572915342949">"Cabeçalho"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 168207d..3a48c3d 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 8c7ffb2..303d669 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Este activat Filtrat"</item>
<item msgid="2779123106632690576">"Activat"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Anteturi filtrate"</item>
- <item msgid="4818549483446395865">"Pachete media A2DP filtrate"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrat"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Dezactivat"</item>
- <item msgid="5884245882825346396">"Magie"</item>
- <item msgid="6569400572915342949">"Antet"</item>
- <item msgid="1239386221416967664">"Filtru complet"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (prestabilit)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index dba7507..e9afb3d 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea pentru alarme și mementouri"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activează"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activează Nu deranja"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 1df0435..4772df98 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Включены фильтры"</item>
<item msgid="2779123106632690576">"Включено"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Применен фильтр по заголовкам"</item>
- <item msgid="4818549483446395865">"Применен фильтр по медиапакетам A2DP"</item>
- <item msgid="8207123990453243311">"Применен фильтр по каналу RFCOMM"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Отключено"</item>
- <item msgid="5884245882825346396">"Специальный параметр"</item>
- <item msgid="6569400572915342949">"Заголовок"</item>
- <item msgid="1239386221416967664">"Общий фильтр"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (по умолчанию)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 76d163c..16788c3 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будильники и напоминания"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Разрешить установку будильников и напоминаний"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники и напоминания"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Если вы разрешите этому приложению устанавливать будильники и планировать на определенное время действия, оно будет работать в фоновом режиме. В таком случае заряд батареи может расходоваться быстрее.\n\nЕсли отключить эту настройку, текущие будильники и созданные приложением мероприятия перестанут запускаться."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Вы можете разрешить этому приложению устанавливать будильники и планировать запуск действий в определенное время. В этом случае оно будет работать в фоновом режиме и быстрее расходовать заряд батареи.\n\nЕсли отключить это разрешение, текущие будильники и созданные приложением события перестанут запускаться."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"установить, будильник, напоминание, часы"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включить"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включите режим \"Не беспокоить\""</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index b516ce6..8de6a71 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"සබල පෙරහන් කළ"</item>
<item msgid="2779123106632690576">"සබලයි"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ශීර්ෂයන් පෙරන ලදි"</item>
- <item msgid="4818549483446395865">"A2DP මාධ්ය පැකට් පෙරන ලදි"</item>
- <item msgid="8207123990453243311">"RFCOMM නාලිකාව පෙරන ලදි"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"අබලයි"</item>
- <item msgid="5884245882825346396">"මැජික්"</item>
- <item msgid="6569400572915342949">"ශීර්ෂකය"</item>
- <item msgid="1239386221416967664">"පූර්ණ පෙරහන"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (පෙරනිමි)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 35c4518..f15dfb7 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Aktivované filtrované"</item>
<item msgid="2779123106632690576">"Aktivované"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Hlavičky sú filtrované"</item>
- <item msgid="4818549483446395865">"Balíky A2DP Media sú filtrované"</item>
- <item msgid="8207123990453243311">"Kanál RFCOMM je filtrovaný"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Deaktivované"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Hlavička"</item>
- <item msgid="1239386221416967664">"Úplný filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predvolené)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5e56aba6..89ef946 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a pripomenutia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povoliť nastavovanie budíkov a pripomenutí"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, súčasné budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 12442a4..9ef852c 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Omogočeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogočeno"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Glave so filtrirane"</item>
- <item msgid="4818549483446395865">"Predstavnostni paketi A2DP so filtrirani"</item>
- <item msgid="8207123990453243311">"Kanal RFCOMM je filtriran"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Onemogočeno"</item>
- <item msgid="5884245882825346396">"Čarovnija"</item>
- <item msgid="6569400572915342949">"Glava"</item>
- <item msgid="1239386221416967664">"Polni filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (privzeto)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 742a86a..89a316d 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Të aktivizuara të filtruara"</item>
<item msgid="2779123106632690576">"Aktiv"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Titujt e filtruar"</item>
- <item msgid="4818549483446395865">"Paketat e medias A2DP të filtruara"</item>
- <item msgid="8207123990453243311">"Kanalet e RFCOMM të filtruara"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Joaktiv"</item>
- <item msgid="5884245882825346396">"Magji"</item>
- <item msgid="6569400572915342949">"Titulli"</item>
- <item msgid="1239386221416967664">"Filtri i plotë"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (I parazgjedhur)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index a338142..e76820e 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Омогућено филтрирано"</item>
<item msgid="2779123106632690576">"Омогућено"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Филтрирана заглавља"</item>
- <item msgid="4818549483446395865">"Филтрирани A2DP медијски пакети"</item>
- <item msgid="8207123990453243311">"Филтрирани RFCOMM канал"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Онемогућено"</item>
- <item msgid="5884245882825346396">"Магија"</item>
- <item msgid="6569400572915342949">"Заглавље"</item>
- <item msgid="1239386221416967664">"Потпуни филтер"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (подразумевано)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index a31c155..391f603 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrering har aktiverats"</item>
<item msgid="2779123106632690576">"Aktiverad"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrerade rubriker"</item>
- <item msgid="4818549483446395865">"Filtrerade A2DP-mediapaket"</item>
- <item msgid="8207123990453243311">"Filtrerad RFCOMM-kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Inaktiverad"</item>
- <item msgid="5884245882825346396">"Magi"</item>
- <item msgid="6569400572915342949">"Rubrik"</item>
- <item msgid="1239386221416967664">"Fullständigt filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 8daf092..1a33b6e4 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Vichujio Vilivyowekwa"</item>
<item msgid="2779123106632690576">"Imewashwa"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Vijajuu Vimechujwa"</item>
- <item msgid="4818549483446395865">"Kifurushi cha Maelezo cha A2DP Kimechujwa"</item>
- <item msgid="8207123990453243311">"Kituo cha RFCOMM Kimechujwa"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Kimezimwa"</item>
- <item msgid="5884245882825346396">"Kiinimacho"</item>
- <item msgid="6569400572915342949">"Kijajuu"</item>
- <item msgid="1239386221416967664">"Kichujio Kamili"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Chaguomsingi)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 8f2fe7e..23eb242 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"இயக்கப்பட்டு வடிகட்டப்பட்டது"</item>
<item msgid="2779123106632690576">"இயக்கப்பட்டது"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"வடிகட்டப்பட்ட தலைப்புப்பகுதிகள்"</item>
- <item msgid="4818549483446395865">"வடிகட்டப்பட்ட A2DP மீடியா பேக்கெட்டுகள்"</item>
- <item msgid="8207123990453243311">"வடிகட்டப்பட்ட RFCOMM சேனல்"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"முடக்கப்பட்டுள்ளது"</item>
- <item msgid="5884245882825346396">"மேஜிக்"</item>
- <item msgid="6569400572915342949">"தலைப்புப்பகுதி"</item>
- <item msgid="1239386221416967664">"முழு வடிப்பான்"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (இயல்பு)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 4b07f37..0f62c1d 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"ప్రారంభించబడింది ఫిల్టర్ చేయబడింది"</item>
<item msgid="2779123106632690576">"ప్రారంభించబడింది"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"హెడర్లు ఫిల్టర్ చేయబడ్డాయి"</item>
- <item msgid="4818549483446395865">"A2DP మీడియా ప్యాకెట్లు ఫిల్టర్ చేయబడ్డాయి"</item>
- <item msgid="8207123990453243311">"RFCOMM ఛానెల్ ఫిల్టర్ చేయబడింది"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"డిజేబుల్ చేయబడింది"</item>
- <item msgid="5884245882825346396">"మ్యాజిక్"</item>
- <item msgid="6569400572915342949">"హెడర్"</item>
- <item msgid="1239386221416967664">"పూర్తి ఫిల్టర్"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.4 (ఆటోమేటిక్ సెట్టింగ్)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index be8dd8b..8d98cdb 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"เปิดใช้รายการที่กรอง"</item>
<item msgid="2779123106632690576">"เปิดใช้"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ส่วนหัวที่กรอง"</item>
- <item msgid="4818549483446395865">"แพ็กเก็ตสื่อ A2DP ที่กรอง"</item>
- <item msgid="8207123990453243311">"แชแนล RFCOMM ที่กรอง"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"ปิดใช้"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"ส่วนหัว"</item>
- <item msgid="1239386221416967664">"ตัวกรองแบบเต็ม"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ค่าเริ่มต้น)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 9b4ae0e..ed47d32 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Na-enable Na-filter"</item>
<item msgid="2779123106632690576">"Naka-enable"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Mga Na-filter na Header"</item>
- <item msgid="4818549483446395865">"Mga Na-filter na A2DP Media Packet"</item>
- <item msgid="8207123990453243311">"Mga Na-filter na RFCOMM Channel"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Naka-disable"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Kumpletong Filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 57c9935..45580f5 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Etkin Filtrelenmiş"</item>
<item msgid="2779123106632690576">"Etkin"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Başlıklar Filtrelendi"</item>
- <item msgid="4818549483446395865">"A2DP Medya Paketleri Filtrelendi"</item>
- <item msgid="8207123990453243311">"RFCOMM Kanalı Filtrelendi"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Devre dışı"</item>
- <item msgid="5884245882825346396">"Sihir"</item>
- <item msgid="6569400572915342949">"Başlık"</item>
- <item msgid="1239386221416967664">"Tam Filtre"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Varsayılan)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 86d53e7..1f56170 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -520,7 +520,7 @@
<string name="okay" msgid="949938843324579502">"Tamam"</string>
<string name="done" msgid="381184316122520313">"Bitti"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmlar ve hatırlatıcılar"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlanmasına izin ver"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlamasına izin ver"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarm kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 53bbb87..f97452c 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Увімкнено з фільтром"</item>
<item msgid="2779123106632690576">"Увімкнено"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Фільтрування за заголовками"</item>
- <item msgid="4818549483446395865">"Фільтрування за пакетами медіаданих A2DP"</item>
- <item msgid="8207123990453243311">"Фільтрування за каналом RFCOMM"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Вимкнено"</item>
- <item msgid="5884245882825346396">"Магія"</item>
- <item msgid="6569400572915342949">"Заголовок"</item>
- <item msgid="1239386221416967664">"Повний фільтр"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (за умовчанням)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 5f82062..74af322 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"فعال کردہ فلٹر کردہ"</item>
<item msgid="2779123106632690576">"فعال"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"ہیڈرز فلٹر کئے گئے"</item>
- <item msgid="4818549483446395865">"A2DP میڈیا پیکٹ فلٹر کیے گئے"</item>
- <item msgid="8207123990453243311">"RFCOMM چینل فلٹر کیا گیا"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"غیر فعال"</item>
- <item msgid="5884245882825346396">"جادو"</item>
- <item msgid="6569400572915342949">"ہیڈر"</item>
- <item msgid="1239386221416967664">"مکمل فلٹر"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ڈیفالٹ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index dc7e6cd..3e53ae6 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrlar yoniq"</item>
<item msgid="2779123106632690576">"Yoniq"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Sarlavhalar filtrlandi"</item>
- <item msgid="4818549483446395865">"A2DP media paketlar filtrlandi"</item>
- <item msgid="8207123990453243311">"RFCOMM kanali filtrlandi"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Faolsizlantirilgan"</item>
- <item msgid="5884245882825346396">"Sehr"</item>
- <item msgid="6569400572915342949">"Sarlavha"</item>
- <item msgid="1239386221416967664">"Toʻliq filtrlash"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (asosiy)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 18e6c57..649cb5c 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Đã bật và lọc"</item>
<item msgid="2779123106632690576">"Đã bật"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Đã lọc tiêu đề"</item>
- <item msgid="4818549483446395865">"Đã lọc gói nội dung nghe nhìn A2DP"</item>
- <item msgid="8207123990453243311">"Đã lọc kênh RFCOMM"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Đã tắt"</item>
- <item msgid="5884245882825346396">"Ảo thuật"</item>
- <item msgid="6569400572915342949">"Tiêu đề"</item>
- <item msgid="1239386221416967664">"Bộ lọc đầy đủ"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Mặc định)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 0d76e6f..13941af 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"已启用“已过滤”"</item>
<item msgid="2779123106632690576">"已启用"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"已过滤标题"</item>
- <item msgid="4818549483446395865">"已过滤 A2DP 媒体数据包"</item>
- <item msgid="8207123990453243311">"已过滤 RFCOMM 通道"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"已停用"</item>
- <item msgid="5884245882825346396">"魔术"</item>
- <item msgid="6569400572915342949">"标题"</item>
- <item msgid="1239386221416967664">"完整过滤器"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5(默认)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index c30e9f7..9b359ed 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"已啟用篩選"</item>
<item msgid="2779123106632690576">"已啟用"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"已篩選標題"</item>
- <item msgid="4818549483446395865">"已篩選 A2DP 媒體封包"</item>
- <item msgid="8207123990453243311">"已篩選 RFCOMM 頻道"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"已停用"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"標題"</item>
- <item msgid="1239386221416967664">"完整篩選器"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index c6073f0..00362d8 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"已啟用篩選結果"</item>
<item msgid="2779123106632690576">"已啟用"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"已篩選標頭"</item>
- <item msgid="4818549483446395865">"已篩選 A2DP 媒體封包"</item>
- <item msgid="8207123990453243311">"已篩選 RFCOMM 管道"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"已停用"</item>
- <item msgid="5884245882825346396">"按偏好排序"</item>
- <item msgid="6569400572915342949">"標頭"</item>
- <item msgid="1239386221416967664">"完整篩選器"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 8bfbd7a..588c4f4 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -230,7 +230,7 @@
<string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯功能"</string>
- <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR 圖碼配對裝置"</string>
+ <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR code 配對裝置"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"使用 QR code 掃描器配對新裝置"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位數的配對碼配對新裝置"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 8b23bbb..ac3cb02 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Okuhlungiwe okunikwe amandla"</item>
<item msgid="2779123106632690576">"Kunikwe amandla"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Izihloko Zihlungiwe"</item>
- <item msgid="4818549483446395865">"I-A2DP Media Packets Ihlungiwe"</item>
- <item msgid="8207123990453243311">"Isiteshi se-RFCOMM Sihlungiwe"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Kukhutshaziwe"</item>
- <item msgid="5884245882825346396">"Umlingo"</item>
- <item msgid="6569400572915342949">"Unhlokweni"</item>
- <item msgid="1239386221416967664">"Isihlungi Esigcwele"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"I-AVRCP 1.5 (Okuzenzakalelayo)"</item>
<item msgid="1637054408779685086">"I-AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 2614644..688fc72 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -55,6 +55,7 @@
public ComponentName settingsComponentName;
public CharSequence description;
public Drawable previewImage;
+ public boolean supportsComplications = false;
@Override
public String toString() {
@@ -175,6 +176,7 @@
if (dreamMetadata != null) {
dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
dreamInfo.previewImage = dreamMetadata.previewImage;
+ dreamInfo.supportsComplications = dreamMetadata.showComplications;
}
dreamInfos.add(dreamInfo);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index 28353ab..52f3111 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -169,8 +169,11 @@
*/
public static boolean maybeShowBatterySaverConfirmation(Context context, Bundle extras) {
if (Secure.getInt(context.getContentResolver(),
- Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
- return false; // Already shown.
+ Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0
+ && Secure.getInt(context.getContentResolver(),
+ Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
+ // Already shown.
+ return false;
}
context.sendBroadcast(
getSystemUiBroadcast(ACTION_SHOW_START_SAVER_CONFIRMATION, extras));
@@ -190,8 +193,10 @@
}
private static void setBatterySaverConfirmationAcknowledged(Context context) {
- Secure.putIntForUser(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1,
- UserHandle.USER_CURRENT);
+ Secure.putIntForUser(context.getContentResolver(),
+ Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1, UserHandle.USER_CURRENT);
+ Secure.putIntForUser(context.getContentResolver(),
+ Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1, UserHandle.USER_CURRENT);
}
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 071ab27..a9d15f3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -97,7 +97,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef({SelectionBehavior.SELECTION_BEHAVIOR_NONE,
- SELECTION_BEHAVIOR_TRANSFER,
+ SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER,
SelectionBehavior.SELECTION_BEHAVIOR_GO_TO_APP
})
public @interface SelectionBehavior {
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 6a1cee3..562d20d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -224,6 +224,9 @@
mMetricsLogger.logOnConditionSelected();
updateAlarmWarningText(tag.condition);
}
+ tag.line1.setStateDescription(
+ isChecked ? buttonView.getContext().getString(
+ com.android.internal.R.string.selected) : null);
}
});
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 87e97b1..abbdaa7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -196,6 +196,9 @@
if (isChecked) {
tag.rb.setChecked(true);
}
+ tag.line1.setStateDescription(
+ isChecked ? buttonView.getContext().getString(
+ com.android.internal.R.string.selected) : null);
}
});
diff --git a/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
index dc8a862..31f014c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
@@ -62,16 +62,7 @@
*/
public Point getTouchInNativeCoordinates(int idx, MotionEvent event,
UdfpsOverlayParams udfpsOverlayParams) {
- Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
- int rot = udfpsOverlayParams.getRotation();
- if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- RotationUtils.rotatePoint(
- portraitTouch,
- RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
- udfpsOverlayParams.getLogicalDisplayWidth(),
- udfpsOverlayParams.getLogicalDisplayHeight()
- );
- }
+ Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams);
// Scale the coordinates to native resolution.
float scale = udfpsOverlayParams.getScaleFactor();
@@ -81,13 +72,25 @@
}
/**
+ * @param idx The pointer identifier.
+ * @param event The MotionEvent object containing full information about the event.
+ * @param udfpsOverlayParams The [UdfpsOverlayParams] used.
+ * @return Whether the touch event is within sensor area.
+ */
+ public boolean isWithinSensorArea(int idx, MotionEvent event,
+ UdfpsOverlayParams udfpsOverlayParams) {
+ Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams);
+ return udfpsOverlayParams.getSensorBounds().contains(portraitTouch.x, portraitTouch.y);
+ }
+
+ /**
* This function computes the angle of touch relative to the sensor and maps the angle to a list
* of help messages which are announced if accessibility is enabled.
*
* @return Whether the announcing string is null
*/
- public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled,
- Context context, int touchX, int touchY, UdfpsOverlayParams udfpsOverlayParams) {
+ public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled, Context context,
+ int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams) {
if (!touchExplorationEnabled) {
return null;
}
@@ -106,8 +109,8 @@
String theStr =
onTouchOutsideOfSensorAreaImpl(
touchHints,
- touchX,
- touchY,
+ scaledTouchX,
+ scaledTouchY,
scaledSensorX,
scaledSensorY,
udfpsOverlayParams.getRotation()
@@ -156,4 +159,22 @@
}
return touchHints[index];
}
+
+ /**
+ * Map the touch to portrait mode if the device is in landscape mode.
+ */
+ private Point getPortraitTouch(int idx, MotionEvent event,
+ UdfpsOverlayParams udfpsOverlayParams) {
+ Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
+ int rot = udfpsOverlayParams.getRotation();
+ if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+ RotationUtils.rotatePoint(
+ portraitTouch,
+ RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
+ udfpsOverlayParams.getLogicalDisplayWidth(),
+ udfpsOverlayParams.getLogicalDisplayHeight()
+ );
+ }
+ return portraitTouch;
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index a15fe9f..ad022a6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -69,6 +69,7 @@
@Test
public void testSetPowerSaveMode_enable_firstCall_needWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isFalse();
@@ -77,15 +78,18 @@
verify(mMockPowerManager, times(0)).setPowerSaveModeEnabled(anyBoolean());
// They shouldn't have changed.
+ assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-1,
- Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-2,
Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_enable_secondCall_needWarning() {
- Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+ // Already acked.
+ Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+ Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
@@ -94,12 +98,17 @@
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_enable_thridCall_needWarning() {
- Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+ // Already acked.
+ Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+ Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
Secure.putInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 1);
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
@@ -108,12 +117,16 @@
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(2, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(2,
+ Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_enable_firstCall_noWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, false)).isTrue();
@@ -122,12 +135,15 @@
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_disable_firstCall_noWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
// When disabling, needFirstTimeWarning doesn't matter.
@@ -137,6 +153,8 @@
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(-1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-2,
Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@@ -144,6 +162,7 @@
@Test
public void testSetPowerSaveMode_disable_firstCall_needWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
// When disabling, needFirstTimeWarning doesn't matter.
@@ -153,6 +172,8 @@
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(-1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-2,
Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 59d5674..6b81c1a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -78,6 +80,8 @@
mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
.thenReturn("testSummary");
+ when(mContext.getString(com.android.internal.R.string.selected))
+ .thenReturn("selected");
NotificationManager.Policy alarmsEnabledPolicy = new NotificationManager.Policy(
NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0);
doReturn(alarmsEnabledPolicy).when(mNotificationManager).getNotificationPolicy();
@@ -190,4 +194,25 @@
// alarm warning should NOT be null
assertNotNull(mController.computeAlarmWarningText(null));
}
+
+ @Test
+ public void testAccessibility() {
+ mController.bindConditions(null);
+ EnableZenModeDialog.ConditionTag forever = mController.getConditionTagAt(
+ ZenDurationDialog.FOREVER_CONDITION_INDEX);
+ EnableZenModeDialog.ConditionTag countdown = mController.getConditionTagAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ EnableZenModeDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+ forever.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+ alwaysAsk.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription()).isNull();
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+ }
}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index 437c0d4..fc45e89 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -205,4 +207,27 @@
ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
assertEquals(120, tag.countdownZenDuration);
}
+
+ @Test
+ public void testAccessibility() {
+ Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+ Settings.Secure.ZEN_DURATION_FOREVER);
+ mController.setupDialog(mBuilder);
+ ZenDurationDialog.ConditionTag forever = mController.getConditionTagAt(
+ ZenDurationDialog.FOREVER_CONDITION_INDEX);
+ ZenDurationDialog.ConditionTag countdown = mController.getConditionTagAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ ZenDurationDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+ forever.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+ alwaysAsk.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription()).isNull();
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+ }
}
\ No newline at end of file
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 210a387..f66fcba 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -142,6 +142,8 @@
Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
Settings.Secure.VOLUME_HUSH_GESTURE,
Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT,
+ Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
+ Settings.Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED,
Settings.Secure.HUSH_GESTURE_USED,
Settings.Secure.IN_CALL_NOTIFICATION_ENABLED,
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
@@ -237,5 +239,6 @@
Settings.Secure.HEARING_AID_CALL_ROUTING,
Settings.Secure.HEARING_AID_MEDIA_ROUTING,
Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
+ Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 39cd24a..558e19f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -219,6 +219,8 @@
COLON_SEPARATED_PACKAGE_LIST_VALIDATOR); // legacy restore setting
VALIDATORS.put(Secure.HUSH_GESTURE_USED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MANUAL_RINGER_TOGGLE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
+ VALIDATORS.put(Secure.LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.IN_CALL_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, BOOLEAN_VALIDATOR);
@@ -374,5 +376,6 @@
new DiscreteValueValidator(new String[] {"0", "1", "2"}));
VALIDATORS.put(Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
new DiscreteValueValidator(new String[] {"0", "1", "2"}));
+ VALIDATORS.put(Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index c2a3ada..a631c81 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -211,6 +211,7 @@
VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.CLOCKWORK_BLUETOOTH_SETTINGS_PREF, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.UNREAD_NOTIFICATION_DOT_INDICATOR, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.AUTO_LAUNCH_MEDIA_CONTROLS, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index fb3c313..1a69208 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1852,6 +1852,9 @@
dumpSetting(s, p,
Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
SecureSettingsProto.Accessibility.HEARING_AID_SYSTEM_SOUNDS_ROUTING);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
+ SecureSettingsProto.Accessibility.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED);
p.end(accessibilityToken);
final long adaptiveSleepToken = p.start(SecureSettingsProto.ADAPTIVE_SLEEP);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c0176d5..ec611cf 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -100,6 +100,7 @@
Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+ Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE,
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific
);
@@ -322,6 +323,7 @@
Settings.Global.LOW_BATTERY_SOUND,
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
Settings.Global.LOW_POWER_MODE,
+ Settings.Global.EXTRA_LOW_POWER_MODE,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
Settings.Global.LOW_POWER_MODE_STICKY,
Settings.Global.LOW_POWER_MODE_SUGGESTION_PARAMS,
@@ -800,7 +802,6 @@
Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
Settings.Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
- Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION,
Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
Settings.Secure.FLASHLIGHT_AVAILABLE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 90bec42..d02e569 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -721,6 +721,7 @@
<!-- Permission required for CTS test - CtsTelephonyTestCases -->
<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
<uses-permission android:name="android.permission.MODIFY_CELL_BROADCASTS" />
+ <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION" />
<!-- Permission required for CTS test - CtsPersistentDataBlockManagerTestCases -->
<uses-permission android:name="android.permission.ACCESS_PDB_STATE" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4e18222..71f438e 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -341,6 +341,8 @@
<uses-permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS" />
+ <uses-permission android:name="android.permission.MONITOR_KEYBOARD_BACKLIGHT" />
+
<protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
index 40a5e97..c49a487 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
@@ -26,7 +26,7 @@
* currently not attached or visible).
*
* @param cujType the CUJ type from the [com.android.internal.jank.InteractionJankMonitor]
- * associated to the launch that will use this controller.
+ * associated to the launch that will use this controller.
*/
fun activityLaunchController(cujType: Int? = null): ActivityLaunchAnimator.Controller?
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
index 9668066..3417ffd 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
@@ -75,7 +75,7 @@
* - Get the associated [Context].
* - Compute whether we are expanding fully above the launch container.
* - Get to overlay to which we initially put the window background layer, until the opening
- * window is made visible (see [openingWindowSyncView]).
+ * window is made visible (see [openingWindowSyncView]).
*
* This container can be changed to force this [Controller] to animate the expanding view
* inside a different location, for instance to ensure correct layering during the
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index b98b9221..ed8e705 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -24,7 +24,7 @@
* Set whether this view should block/postpone all calls to [View.setVisibility]. This ensures
* that this view:
* - remains invisible during the launch animation given that it is ghosted and already drawn
- * somewhere else.
+ * somewhere else.
* - remains invisible as long as a dialog expanded from it is shown.
* - restores its expected visibility once the dialog expanded from it is dismissed.
*
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
index 0e2d23b..6946e6b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
@@ -182,9 +182,9 @@
* Represents a TransitionInfo object as an array of old-style targets
*
* @param wallpapers If true, this will return wallpaper targets; otherwise it returns
- * non-wallpaper targets.
+ * non-wallpaper targets.
* @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should
- * be populated by this function. If null, it is ignored.
+ * be populated by this function. If null, it is ignored.
*/
fun wrapTargets(
info: TransitionInfo,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
index a96f893..b89a8b0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
@@ -6,6 +6,7 @@
/**
* Interpolate alpha for notification background scrim during shade expansion.
+ *
* @param fraction Shade expansion fraction
*/
@JvmStatic
@@ -16,6 +17,7 @@
/**
* Interpolate alpha for shade content during shade expansion.
+ *
* @param fraction Shade expansion fraction
*/
@JvmStatic
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index 341784e..468a8b1 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -161,7 +161,6 @@
* This API is useful to continue animation from the middle of the state. For example, if you
* animate weight from 200 to 400, then if you want to move back to 200 at the half of the
* animation, it will look like
- *
* <pre> <code>
* ```
* val interp = TextInterpolator(layout)
@@ -497,7 +496,9 @@
count,
layout.textDirectionHeuristic,
paint
- ) { _, _, glyphs, _ -> runs.add(glyphs) }
+ ) { _, _, glyphs, _ ->
+ runs.add(glyphs)
+ }
out.add(runs)
if (lineNo > 0) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index 052888b..b5b6037 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -25,7 +25,6 @@
/**
* Shader class that renders an expanding ripple effect. The ripple contains three elements:
- *
* 1. an expanding filled [RippleShape] that appears in the beginning and quickly fades away
* 2. an expanding ring that appears throughout the effect
* 3. an expanding ring-shaped area that reveals noise over #2.
@@ -317,6 +316,7 @@
* Parameters used for fade in and outs of the ripple.
*
* <p>Note that all the fade in/ outs are "linear" progression.
+ *
* ```
* (opacity)
* 1
@@ -331,6 +331,7 @@
* fadeIn fadeOut
* Start & End Start & End
* ```
+ *
* <p>If no fade in/ out is needed, set [fadeInStart] and [fadeInEnd] to 0; [fadeOutStart] and
* [fadeOutEnd] to 1.
*/
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 79bc2f4..89871fa7 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -30,12 +30,14 @@
* Noise move speed variables.
*
* Its sign determines the direction; magnitude determines the speed. <ul>
+ *
* ```
* <li> [noiseMoveSpeedX] positive: right to left; negative: left to right.
* <li> [noiseMoveSpeedY] positive: bottom to top; negative: top to bottom.
* <li> [noiseMoveSpeedZ] its sign doesn't matter much, as it moves in Z direction. Use it
* to add turbulence in place.
* ```
+ *
* </ul>
*/
val noiseMoveSpeedX: Float = 0f,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
new file mode 100644
index 0000000..35dbb89
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.util
+
+import androidx.core.animation.Animator
+
+/**
+ * Add an action which will be invoked when the animation has ended.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.end
+ */
+inline fun Animator.doOnEnd(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onEnd = action)
+
+/**
+ * Add an action which will be invoked when the animation has started.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.start
+ */
+inline fun Animator.doOnStart(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onStart = action)
+
+/**
+ * Add an action which will be invoked when the animation has been cancelled.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.cancel
+ */
+inline fun Animator.doOnCancel(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onCancel = action)
+
+/**
+ * Add an action which will be invoked when the animation has repeated.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.doOnRepeat(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onRepeat = action)
+
+/**
+ * Add a listener to this Animator using the provided actions.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.addListener(
+ crossinline onEnd: (animator: Animator) -> Unit = {},
+ crossinline onStart: (animator: Animator) -> Unit = {},
+ crossinline onCancel: (animator: Animator) -> Unit = {},
+ crossinline onRepeat: (animator: Animator) -> Unit = {}
+): Animator.AnimatorListener {
+ val listener =
+ object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animator: Animator) = onRepeat(animator)
+ override fun onAnimationEnd(animator: Animator) = onEnd(animator)
+ override fun onAnimationCancel(animator: Animator) = onCancel(animator)
+ override fun onAnimationStart(animator: Animator) = onStart(animator)
+ }
+ addListener(listener)
+ return listener
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
new file mode 100644
index 0000000..30e2a25
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Context
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UClass
+
+/**
+ * Checks if any class has implemented the `Dumpable` interface but has not registered itself with
+ * the `DumpManager`.
+ */
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetector : Detector(), SourceCodeScanner {
+
+ private var isDumpable: Boolean = false
+ private var isCoreStartable: Boolean = false
+ private var hasRegisterCall: Boolean = false
+ private var classLocation: Location? = null
+
+ override fun beforeCheckFile(context: Context) {
+ isDumpable = false
+ isCoreStartable = false
+ hasRegisterCall = false
+ classLocation = null
+ }
+
+ override fun applicableSuperClasses(): List<String> {
+ return listOf(DUMPABLE_CLASS_NAME)
+ }
+
+ override fun getApplicableMethodNames(): List<String> {
+ return listOf("registerDumpable", "registerNormalDumpable", "registerCriticalDumpable")
+ }
+
+ override fun visitClass(context: JavaContext, declaration: UClass) {
+ if (declaration.isInterface || context.evaluator.isAbstract(declaration)) {
+ // Don't require interfaces or abstract classes to call `register` (assume the full
+ // implementations will call it). This also means that we correctly don't warn for the
+ // `Dumpable` interface itself.
+ return
+ }
+
+ classLocation = context.getNameLocation(declaration)
+
+ val superTypeClassNames = declaration.superTypes.mapNotNull { it.resolve()?.qualifiedName }
+ isDumpable = superTypeClassNames.contains(DUMPABLE_CLASS_NAME)
+ isCoreStartable = superTypeClassNames.contains(CORE_STARTABLE_CLASS_NAME)
+ }
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ if (context.evaluator.isMemberInSubClassOf(method, DUMP_MANAGER_CLASS_NAME)) {
+ hasRegisterCall = true
+ }
+ }
+
+ override fun afterCheckFile(context: Context) {
+ if (!isDumpable) {
+ return
+ }
+ if (isDumpable && isCoreStartable) {
+ // CoreStartables will be automatically registered, so classes that implement
+ // CoreStartable do not need a `register` call.
+ return
+ }
+
+ if (!hasRegisterCall) {
+ context.report(
+ issue = ISSUE,
+ location = classLocation!!,
+ message =
+ "Any class implementing `Dumpable` must call " +
+ "`DumpManager.registerNormalDumpable` or " +
+ "`DumpManager.registerCriticalDumpable`",
+ )
+ }
+ }
+
+ companion object {
+ @JvmField
+ val ISSUE: Issue =
+ Issue.create(
+ id = "DumpableNotRegistered",
+ briefDescription = "Dumpable not registered with DumpManager.",
+ explanation =
+ """
+ This class has implemented the `Dumpable` interface, but it has not registered \
+ itself with the `DumpManager`. This means that the class will never actually \
+ be dumped. Please call `DumpManager.registerNormalDumpable` or \
+ `DumpManager.registerCriticalDumpable` in the class's constructor or \
+ initialization method.""",
+ category = Category.CORRECTNESS,
+ priority = 8,
+ severity = Severity.WARNING,
+ implementation =
+ Implementation(DumpableNotRegisteredDetector::class.java, Scope.JAVA_FILE_SCOPE)
+ )
+
+ private const val DUMPABLE_CLASS_NAME = "com.android.systemui.Dumpable"
+ private const val CORE_STARTABLE_CLASS_NAME = "com.android.systemui.CoreStartable"
+ private const val DUMP_MANAGER_CLASS_NAME = "com.android.systemui.dump.DumpManager"
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 254a6fb..84f7050 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -32,6 +32,7 @@
BindServiceOnMainThreadDetector.ISSUE,
BroadcastSentViaContextDetector.ISSUE,
CleanArchitectureDependencyViolationDetector.ISSUE,
+ DumpableNotRegisteredDetector.ISSUE,
SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
NonInjectedMainThreadDetector.ISSUE,
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
index a4b59fd..a5f832a 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
@@ -64,7 +64,8 @@
class BadClass(
private val viewModel: ViewModel,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -98,7 +99,8 @@
class BadClass(
private val repository: Repository,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -136,7 +138,8 @@
private val interactor: Interactor,
private val viewmodel: ViewModel,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -176,7 +179,8 @@
class BadClass(
private val interactor: Interactor,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -207,7 +211,8 @@
data class Model(
private val name: String,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
private val REPOSITORY_FILE =
TestFiles.kotlin(
@@ -228,7 +233,8 @@
return models
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val INTERACTOR_FILE =
TestFiles.kotlin(
@@ -245,7 +251,8 @@
return repository.getModels()
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val VIEW_MODEL_FILE =
TestFiles.kotlin(
@@ -262,7 +269,8 @@
return interactor.getModels().map { model -> model.name }
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val NON_CLEAN_ARCHITECTURE_FILE =
TestFiles.kotlin(
@@ -282,7 +290,8 @@
)
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val LEGITIMATE_FILES =
arrayOf(
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
new file mode 100644
index 0000000..3d6cbc7
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector = DumpableNotRegisteredDetector()
+
+ override fun getIssues(): List<Issue> = listOf(DumpableNotRegisteredDetector.ISSUE)
+
+ @Test
+ fun classIsNotDumpable_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ class SomeClass() {
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterNormalIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerNormalDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterCriticalIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerCriticalDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_noRegister_violation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+
+ public class SomeClass implements Dumpable {
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expect(
+ ("""
+ src/test/pkg/SomeClass.java:5: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+ public class SomeClass implements Dumpable {
+ ~~~~~~~~~
+ 0 errors, 1 warnings
+ """)
+ .trimIndent()
+ )
+ }
+
+ @Test
+ fun classIsDumpable_usesNotDumpManagerMethod_violation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.OtherRegistrationObject;
+
+ public class SomeClass implements Dumpable {
+ public SomeClass(OtherRegistrationObject otherRegistrationObject) {
+ otherRegistrationObject.registerDumpable(this);
+ }
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expect(
+ ("""
+ src/test/pkg/SomeClass.java:6: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+ public class SomeClass implements Dumpable {
+ ~~~~~~~~~
+ 0 errors, 1 warnings
+ """)
+ .trimIndent()
+ )
+ }
+
+ @Test
+ fun classIsDumpableAndCoreStartable_noRegister_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.CoreStartable;
+
+ public class SomeClass implements Dumpable, CoreStartable {
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsAbstract_noRegister_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+
+ public abstract class SomeClass implements Dumpable {
+ void abstractMethodHere();
+
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ companion object {
+ private val DUMPABLE_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ import com.android.systemui.dump.DumpManager;
+ import java.io.PrintWriter;
+
+ public interface Dumpable {
+ void dump();
+ }
+ """
+ )
+ .indented()
+
+ private val DUMP_MANAGER_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui.dump;
+
+ public interface DumpManager {
+ void registerDumpable(Dumpable module);
+ void registerNormalDumpable(Dumpable module);
+ void registerCriticalDumpable(Dumpable module);
+ }
+ """
+ )
+ .indented()
+
+ private val OTHER_REGISTRATION_OBJECT_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ public interface OtherRegistrationObject {
+ void registerDumpable(Dumpable module);
+ }
+ """
+ )
+ .indented()
+
+ private val CORE_STARTABLE_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ public interface CoreStartable {
+ void start();
+ }
+ """
+ )
+ .indented()
+
+ private val stubs =
+ arrayOf(
+ DUMPABLE_STUB,
+ DUMP_MANAGER_STUB,
+ OTHER_REGISTRATION_OBJECT_STUB,
+ CORE_STARTABLE_STUB,
+ )
+ }
+}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
index a02954a..08ab146 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
@@ -78,11 +78,10 @@
* Set the status bar color.
*
* @param color The **desired** [Color] to set. This may require modification if running on an
- * API level that only supports white status bar icons.
+ * API level that only supports white status bar icons.
* @param darkIcons Whether dark status bar icons would be preferable.
* @param transformColorForLightContent A lambda which will be invoked to transform [color] if
- * dark icons were requested but are not available. Defaults to applying a black scrim.
- *
+ * dark icons were requested but are not available. Defaults to applying a black scrim.
* @see statusBarDarkContentEnabled
*/
fun setStatusBarColor(
@@ -95,16 +94,15 @@
* Set the navigation bar color.
*
* @param color The **desired** [Color] to set. This may require modification if running on an
- * API level that only supports white navigation bar icons. Additionally this will be ignored
- * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the
- * system UI automatically applies background protection in other navigation modes.
+ * API level that only supports white navigation bar icons. Additionally this will be ignored
+ * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or
+ * the system UI automatically applies background protection in other navigation modes.
* @param darkIcons Whether dark navigation bar icons would be preferable.
* @param navigationBarContrastEnforced Whether the system should ensure that the navigation bar
- * has enough contrast when a fully transparent background is requested. Only supported on API
- * 29+.
+ * has enough contrast when a fully transparent background is requested. Only supported on API
+ * 29+.
* @param transformColorForLightContent A lambda which will be invoked to transform [color] if
- * dark icons were requested but are not available. Defaults to applying a black scrim.
- *
+ * dark icons were requested but are not available. Defaults to applying a black scrim.
* @see navigationBarDarkContentEnabled
* @see navigationBarContrastEnforced
*/
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index cfc38df..d4a81f9 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -255,7 +255,9 @@
.onGloballyPositioned {
controller.boundsInComposeViewRoot.value = it.boundsInRoot()
}
- ) { wrappedContent(controller.expandable) }
+ ) {
+ wrappedContent(controller.expandable)
+ }
}
else -> {
val clickModifier =
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
index edb10c7d..767756e 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
@@ -156,9 +156,9 @@
* Create a [LaunchAnimator.Controller] that is going to be used to drive an activity or dialog
* animation. This controller will:
* 1. Compute the start/end animation state using [boundsInComposeViewRoot] and the location of
- * composeViewRoot on the screen.
+ * composeViewRoot on the screen.
* 2. Update [animatorState] with the current animation state if we are animating, or null
- * otherwise.
+ * otherwise.
*/
private fun launchController(): LaunchAnimator.Controller {
return object : LaunchAnimator.Controller {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
index eb9d625..a80a1f9 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
@@ -86,21 +86,20 @@
/**
* A horizontally scrolling layout that allows users to flip between items to the left and right.
*
- * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
- *
* @param count the number of pages.
* @param modifier the modifier to apply to this layout.
* @param state the state object to be used to control or observe the pager's state.
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item is
- * located at the end.
+ * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item
+ * is located at the end.
* @param itemSpacing horizontal spacing to add between items.
* @param flingBehavior logic describing fling behavior.
* @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ * [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
*/
@ExperimentalPagerApi
@Composable
@@ -134,21 +133,20 @@
/**
* A vertically scrolling layout that allows users to flip between items to the top and bottom.
*
- * @sample com.google.accompanist.sample.pager.VerticalPagerSample
- *
* @param count the number of pages.
* @param modifier the modifier to apply to this layout.
* @param state the state object to be used to control or observe the pager's state.
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item is
- * located at the bottom.
+ * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item
+ * is located at the bottom.
* @param itemSpacing vertical spacing to add between items.
* @param flingBehavior logic describing fling behavior.
* @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ * [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.VerticalPagerSample
*/
@ExperimentalPagerApi
@Composable
@@ -246,7 +244,9 @@
// Constraint the content to be <= than the size of the pager.
.fillParentMaxHeight()
.wrapContentSize()
- ) { pagerScope.content(page) }
+ ) {
+ pagerScope.content(page)
+ }
}
}
} else {
@@ -272,7 +272,9 @@
// Constraint the content to be <= than the size of the pager.
.fillParentMaxWidth()
.wrapContentSize()
- ) { pagerScope.content(page) }
+ ) {
+ pagerScope.content(page)
+ }
}
}
}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
index 2e6ae78..1822a68 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
@@ -198,7 +198,7 @@
*
* @param page the page to animate to. Must be between 0 and [pageCount] (inclusive).
* @param pageOffset the percentage of the page width to offset, from the start of [page]. Must
- * be in the range 0f..1f.
+ * be in the range 0f..1f.
*/
suspend fun animateScrollToPage(
@IntRange(from = 0) page: Int,
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
index 23122de..9814029 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
@@ -44,11 +44,11 @@
/**
* Create and remember a snapping [FlingBehavior] to be used with [LazyListState].
*
- * TODO: move this to a new module and make it public
- *
* @param lazyListState The [LazyListState] to update.
* @param decayAnimationSpec The decay animation spec to use for decayed flings.
* @param snapAnimationSpec The animation spec to use when snapping.
+ *
+ * TODO: move this to a new module and make it public
*/
@Composable
internal fun rememberSnappingFlingBehavior(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
index 3eeadae..a74e56b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
@@ -60,7 +60,7 @@
*
* @param viewModel the [PeopleViewModel] that should be composed.
* @param onResult the callback called with the result of this screen. Callers should usually finish
- * the Activity/Fragment/View hosting this Composable once a result is available.
+ * the Activity/Fragment/View hosting this Composable once a result is available.
*/
@Composable
fun PeopleScreen(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
index 3f590df..0484ff4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
@@ -79,7 +79,9 @@
containerColor = androidColors.colorAccentPrimary,
contentColor = androidColors.textColorOnAccent,
)
- ) { Text(stringResource(R.string.got_it)) }
+ ) {
+ Text(stringResource(R.string.got_it))
+ }
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index ab36d58..00c0a0b 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -38,6 +38,7 @@
private val TAG = ClockRegistry::class.simpleName!!
private const val DEBUG = true
+private val KEY_TIMESTAMP = "appliedTimestamp"
/** ClockRegistry aggregates providers and plugins */
open class ClockRegistry(
@@ -134,9 +135,9 @@
assertNotMainThread()
try {
- value?._applied_timestamp = System.currentTimeMillis()
- val json = ClockSettings.serialize(value)
+ value?.metadata?.put(KEY_TIMESTAMP, System.currentTimeMillis())
+ val json = ClockSettings.serialize(value)
if (handleAllUsers) {
Settings.Secure.putStringForUser(
context.contentResolver,
@@ -172,7 +173,7 @@
clockChangeListeners.forEach(func)
}
- private fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
+ public fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
scope.launch(bgDispatcher) { applySettings(mutator(settings ?: ClockSettings())) }
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 2a40f5c..4df7a44 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -95,7 +95,7 @@
open inner class DefaultClockFaceController(
override val view: AnimatableClockView,
- val seedColor: Int?,
+ var seedColor: Int?,
) : ClockFaceController {
// MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -111,9 +111,9 @@
init {
if (seedColor != null) {
- currentColor = seedColor
+ currentColor = seedColor!!
}
- view.setColors(currentColor, currentColor)
+ view.setColors(DOZE_COLOR, currentColor)
}
override val events =
@@ -141,7 +141,7 @@
fun updateColor() {
val color =
if (seedColor != null) {
- seedColor
+ seedColor!!
} else if (isRegionDark) {
resources.getColor(android.R.color.system_accent1_100)
} else {
@@ -194,6 +194,14 @@
smallClock.updateColor()
}
+ override fun onSeedColorChanged(seedColor: Int?) {
+ largeClock.seedColor = seedColor
+ smallClock.seedColor = seedColor
+
+ largeClock.updateColor()
+ smallClock.updateColor()
+ }
+
override fun onLocaleChanged(locale: Locale) {
val nf = NumberFormat.getInstance(locale)
if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
index c120876..0d88075 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
@@ -51,7 +51,7 @@
*
* Supported operations:
* - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result
- * set will contain rows with the [SlotTable.Columns] columns.
+ * set will contain rows with the [SlotTable.Columns] columns.
*/
object SlotTable {
const val TABLE_NAME = "slots"
@@ -74,8 +74,8 @@
*
* Supported operations:
* - Query - to know about all the affordances that are available on the device, regardless
- * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
- * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
+ * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
+ * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
*/
object AffordanceTable {
const val TABLE_NAME = "affordances"
@@ -128,14 +128,14 @@
*
* Supported operations:
* - Insert - to insert an affordance and place it in a slot, insert values for the columns
- * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
- * Selecting a new affordance for a slot that is already full will automatically remove the
- * oldest affordance from the slot.
+ * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the
+ * system. Selecting a new affordance for a slot that is already full will automatically
+ * remove the oldest affordance from the slot.
* - Query - to know which affordances are set on which slots, query the
- * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
- * columns from [SelectionTable.Columns].
+ * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
+ * columns from [SelectionTable.Columns].
* - Delete - to unselect an affordance, removing it from a slot, delete from the
- * [SelectionTable.URI] [Uri], passing in values for each column.
+ * [SelectionTable.URI] [Uri], passing in values for each column.
*/
object SelectionTable {
const val TABLE_NAME = "selections"
@@ -160,7 +160,7 @@
*
* Supported operations:
* - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
- * contain rows, each of which with the columns from [FlagsTable.Columns].
+ * contain rows, each of which with the columns from [FlagsTable.Columns].
*/
object FlagsTable {
const val TABLE_NAME = "flags"
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index ec860b5..18753fd 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -1,28 +1,20 @@
+packages/SystemUI
-packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
-packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
-packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
--packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
@@ -35,8 +27,6 @@
-packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
-packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
-packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
@@ -65,12 +55,10 @@
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
-packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
@@ -80,7 +68,6 @@
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyViewController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -93,8 +80,6 @@
-packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
-packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
-packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
-packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
-packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
@@ -102,7 +87,6 @@
-packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
-packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
-packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
--packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -132,6 +116,7 @@
-packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
-packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
-packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
@@ -162,7 +147,6 @@
-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
-packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
--packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
-packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
-packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
-packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -172,20 +156,16 @@
-packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
-packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
-packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/Flags.kt
-packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
-packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
-packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
--packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
-packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
--packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
--packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
-packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
--packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
@@ -202,9 +182,15 @@
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTasksAdapter.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+-packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
-packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
-packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt
-packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt
@@ -220,8 +206,6 @@
-packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
-packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
-packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
-packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
-packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
@@ -237,7 +221,6 @@
-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -245,10 +228,6 @@
-packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
-packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
--packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
-packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
-packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
@@ -259,23 +238,21 @@
-packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
-packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
-packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
--packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
-packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
-packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
-packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
-packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
--packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
-packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
--packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
-packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
-packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
-packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeHeightLogger.kt
-packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
-packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
-packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
-packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
-packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -284,9 +261,7 @@
-packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
-packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
-packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
--packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
@@ -311,10 +286,12 @@
-packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableFlagsLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
@@ -325,7 +302,6 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
@@ -403,6 +379,7 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
@@ -444,13 +421,10 @@
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/ShadeStateListener.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -470,19 +444,17 @@
-packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
-packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
-packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
-packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
--packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
--packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
-packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
-packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
-packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
@@ -509,7 +481,6 @@
-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
-packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
--packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
-packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
-packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
-packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
@@ -517,6 +488,7 @@
-packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
-packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
-packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/recycler/HorizontalSpacerItemDecoration.kt
-packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
-packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
-packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
@@ -525,7 +497,6 @@
-packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
--packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
@@ -549,8 +520,6 @@
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
@@ -569,7 +538,6 @@
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -579,7 +547,6 @@
-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
@@ -596,13 +563,17 @@
-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
-packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
--packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
-packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
@@ -610,7 +581,6 @@
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
@@ -641,35 +611,28 @@
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
--packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -683,6 +646,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -719,7 +683,6 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
@@ -733,8 +696,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/ShadeExpansionStateManagerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
@@ -744,7 +706,6 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
@@ -753,40 +714,34 @@
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
-packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
-packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
--packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
--packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt
-packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
--packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 314c736..db88b59 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -171,7 +171,7 @@
a1 = TonalSpec(HueSource(), ChromaConstant(36.0)),
a2 = TonalSpec(HueSource(), ChromaConstant(16.0)),
a3 = TonalSpec(HueAdd(60.0), ChromaConstant(24.0)),
- n1 = TonalSpec(HueSource(), ChromaConstant(4.0)),
+ n1 = TonalSpec(HueSource(), ChromaConstant(6.0)),
n2 = TonalSpec(HueSource(), ChromaConstant(8.0))
)),
VIBRANT(CoreSpec(
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
index 3a6b362..e6b2c2f 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
@@ -350,7 +350,7 @@
if (bgDynamicColor != null) {
final boolean bgHasBg =
bgDynamicColor.background != null && bgDynamicColor.background.apply(scheme)
- == null;
+ != null;
final double standardRatio =
Contrast.ratioOfTones(tone.apply(scheme), bgDynamicColor.tone.apply(scheme));
if (decreasingContrast) {
@@ -358,15 +358,15 @@
Contrast.ratioOfTones(
toneMinContrast.apply(scheme),
bgDynamicColor.toneMinContrast.apply(scheme));
- minRatio = bgHasBg ? 1.0 : minContrastRatio;
+ minRatio = bgHasBg ? minContrastRatio : 1.0;
maxRatio = standardRatio;
} else {
final double maxContrastRatio =
Contrast.ratioOfTones(
toneMaxContrast.apply(scheme),
bgDynamicColor.toneMaxContrast.apply(scheme));
- minRatio = !bgHasBg ? 1.0 : min(maxContrastRatio, standardRatio);
- maxRatio = !bgHasBg ? 21.0 : max(maxContrastRatio, standardRatio);
+ minRatio = bgHasBg ? min(maxContrastRatio, standardRatio) : 1.0;
+ maxRatio = bgHasBg ? max(maxContrastRatio, standardRatio) : 21.0;
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index ab4aca5..babe5700 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -112,6 +112,9 @@
/** Call whenever the color palette should update */
fun onColorPaletteChanged(resources: Resources) {}
+ /** Call if the seed color has changed and should be updated */
+ fun onSeedColorChanged(seedColor: Int?) {}
+
/** Call whenever the weather data should update */
fun onWeatherDataChanged(data: WeatherData) {}
}
@@ -189,12 +192,13 @@
val clockId: ClockId? = null,
val seedColor: Int? = null,
) {
- var _applied_timestamp: Long? = null
+ // Exclude metadata from equality checks
+ var metadata: JSONObject = JSONObject()
companion object {
private val KEY_CLOCK_ID = "clockId"
private val KEY_SEED_COLOR = "seedColor"
- private val KEY_TIMESTAMP = "_applied_timestamp"
+ private val KEY_METADATA = "metadata"
fun serialize(setting: ClockSettings?): String {
if (setting == null) {
@@ -204,7 +208,7 @@
return JSONObject()
.put(KEY_CLOCK_ID, setting.clockId)
.put(KEY_SEED_COLOR, setting.seedColor)
- .put(KEY_TIMESTAMP, setting._applied_timestamp)
+ .put(KEY_METADATA, setting.metadata)
.toString()
}
@@ -216,11 +220,11 @@
val json = JSONObject(jsonStr)
val result =
ClockSettings(
- json.getString(KEY_CLOCK_ID),
+ if (!json.isNull(KEY_CLOCK_ID)) json.getString(KEY_CLOCK_ID) else null,
if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null
)
- if (!json.isNull(KEY_TIMESTAMP)) {
- result._applied_timestamp = json.getLong(KEY_TIMESTAMP)
+ if (!json.isNull(KEY_METADATA)) {
+ result.metadata = json.getJSONObject(KEY_METADATA)
}
return result
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
index e99b214..3e34885 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
@@ -35,7 +35,6 @@
* as the result of taking a bug report).
*
* You can dump the entire buffer at any time by running:
- *
* ```
* $ adb shell dumpsys activity service com.android.systemui/.SystemUIService <bufferName>
* ```
@@ -46,13 +45,11 @@
* locally (usually for debugging purposes).
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* $ adb shell settings put global systemui/buffer/<bufferName> <level>
* ```
*
* To enable logcat echoing for a specific tag:
- *
* ```
* $ adb shell settings put global systemui/tag/<tag> <level>
* ```
@@ -64,10 +61,10 @@
* LogBufferFactory.
*
* @param name The name of this buffer, printed when the buffer is dumped and in some other
- * situations.
+ * situations.
* @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
- * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches the
- * maximum, it behaves like a ring buffer.
+ * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
+ * the maximum, it behaves like a ring buffer.
*/
class LogBuffer
@JvmOverloads
@@ -116,22 +113,22 @@
* initializer stored and converts it to a human-readable log message.
*
* @param tag A string of at most 23 characters, used for grouping logs into categories or
- * subjects. If this message is echoed to logcat, this will be the tag that is used.
+ * subjects. If this message is echoed to logcat, this will be the tag that is used.
* @param level Which level to log the message at, both to the buffer and to logcat if it's
- * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
- * INFO level should be reserved for information that other parts of the system might care
- * about, leaving the specifics of code's day-to-day operations to DEBUG.
+ * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
+ * INFO level should be reserved for information that other parts of the system might care
+ * about, leaving the specifics of code's day-to-day operations to DEBUG.
* @param messageInitializer A function that will be called immediately to store relevant data
- * on the log message. The value of `this` will be the LogMessage to be initialized.
+ * on the log message. The value of `this` will be the LogMessage to be initialized.
* @param messagePrinter A function that will be called if and when the message needs to be
- * dumped to logcat or a bug report. It should read the data stored by the initializer and
- * convert it to a human-readable string. The value of `this` will be the LogMessage to be
- * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
- * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
- * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
- * allocation.
+ * dumped to logcat or a bug report. It should read the data stored by the initializer and
+ * convert it to a human-readable string. The value of `this` will be the LogMessage to be
+ * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
+ * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
+ * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
+ * allocation.
* @param exception Provide any exception that need to be logged. This is saved as
- * [LogMessage.exception]
+ * [LogMessage.exception]
*/
@JvmOverloads
inline fun log(
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
index faf1b78..7a125ac 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
@@ -28,7 +28,6 @@
* Version of [LogcatEchoTracker] for debuggable builds
*
* The log level of individual buffers or tags can be controlled via global settings:
- *
* ```
* # Echo any message to <bufferName> of <level> or higher
* $ adb shell settings put global systemui/buffer/<bufferName> <level>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
index 68d7890..4773f54 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
@@ -30,7 +30,7 @@
*
* @param maxSize The maximum size the buffer can grow to before it begins functioning as a ring.
* @param factory A function that creates a fresh instance of T. Used by the buffer while it's
- * growing to [maxSize].
+ * growing to [maxSize].
*/
class RingBuffer<T>(private val maxSize: Int, private val factory: () -> T) : Iterable<T> {
diff --git a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
deleted file mode 100644
index 2e259c3..0000000
--- a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
deleted file mode 100644
index f4de96a..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
similarity index 100%
rename from packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png
rename to packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
index 411fea5..48769fd 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
@@ -14,10 +14,12 @@
~ limitations under the License
-->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:id="@+id/digit_text"
style="@style/Widget.TextView.NumPadKey.Digit"
+ android:autoSizeMaxTextSize="32sp"
+ android:autoSizeTextType="uniform"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 7db0fe9..728d861 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
**
** Copyright 2012, The Android Open Source Project
**
@@ -17,185 +16,185 @@
*/
-->
<!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
-<com.android.keyguard.KeyguardSimPinView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
- android:id="@+id/keyguard_sim_pin_view"
- android:orientation="vertical"
+<com.android.keyguard.KeyguardSimPinView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_sim_pin_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+ android:layout_gravity="center_horizontal|bottom">
+ <include layout="@layout/keyguard_bouncer_message_area"/>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- androidprv:layout_maxWidth="@dimen/keyguard_security_width"
- android:layout_gravity="center_horizontal|bottom">
- <include layout="@layout/keyguard_bouncer_message_area" />
- <Space
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
- <ImageView
- android:id="@+id/keyguard_sim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:tint="@color/background_protected"
- android:src="@drawable/ic_lockscreen_sim"/>
- <LinearLayout
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layoutDirection="ltr">
+ <LinearLayout
+ android:id="@+id/pin_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:gravity="center"
- android:layoutDirection="ltr"
- >
- <include layout="@layout/keyguard_esim_area"
- android:id="@+id/keyguard_esim_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <RelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="4dp"
- >
+ android:gravity="center_horizontal"
+ android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toTopOf="parent">
+
+ <ImageView
+ android:id="@+id/keyguard_sim"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_lockscreen_sim"
+ app:tint="@color/background_protected" />
+
+ <include
+ android:id="@+id/keyguard_esim_area"
+ layout="@layout/keyguard_esim_area"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
<com.android.keyguard.PasswordTextView
android:id="@+id/simPinEntry"
style="@style/Widget.TextView.Password"
android:layout_width="@dimen/keyguard_security_width"
android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
- android:gravity="center"
+ android:layout_gravity="center_horizontal"
androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </RelativeLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="1"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="2"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="3"
- />
</LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="4"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="5"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="6"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="7"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="8"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="9"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- >
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- android:contentDescription="@string/keyboardview_keycode_delete"
- style="@style/NumPadKey.Delete"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="0"
- />
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- style="@style/NumPadKey.Enter"
- android:contentDescription="@string/keyboardview_keycode_enter"
- />
- </LinearLayout>
- </LinearLayout>
- <include layout="@layout/keyguard_eca"
- android:id="@+id/keyguard_selector_fade_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:layout_marginBottom="2dp"
- android:gravity="center_horizontal"/>
+
+ <androidx.constraintlayout.helper.widget.Flow
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/simPinEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/simPinEntry" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <include
+ android:id="@+id/keyguard_selector_fade_container"
+ layout="@layout/keyguard_eca"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_marginBottom="2dp"
+ android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+ android:gravity="center_horizontal"
+ android:orientation="vertical" />
</com.android.keyguard.KeyguardSimPinView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 422bd4c..7e24d12 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -21,6 +21,7 @@
<com.android.keyguard.KeyguardSimPukView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_sim_puk_view"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -29,173 +30,165 @@
android:layout_gravity="center_horizontal|bottom">
<include layout="@layout/keyguard_bouncer_message_area"/>
- <Space
+ <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="1" />
-
- <ImageView
- android:id="@+id/keyguard_sim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:tint="@color/background_protected"
- android:src="@drawable/ic_lockscreen_sim"/>
-
- <LinearLayout
+ android:layout_weight="1"
+ android:layoutDirection="ltr">
+ <LinearLayout
+ android:id="@+id/pin_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:gravity="center"
- android:layoutDirection="ltr"
- >
- <include layout="@layout/keyguard_esim_area"
- android:id="@+id/keyguard_esim_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:gravity="center_horizontal"
+ android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toTopOf="parent">
- <RelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="4dp"
- >
+ <ImageView
+ android:id="@+id/keyguard_sim"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_lockscreen_sim"
+ app:tint="@color/background_protected" />
+
+ <include
+ android:id="@+id/keyguard_esim_area"
+ layout="@layout/keyguard_esim_area"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
<com.android.keyguard.PasswordTextView
android:id="@+id/pukEntry"
style="@style/Widget.TextView.Password"
android:layout_width="@dimen/keyguard_security_width"
android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
- android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
- android:gravity="center"
+ android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
+ android:layout_gravity="center_horizontal"
androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </RelativeLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="1"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="2"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="3"
- />
</LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="4"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="5"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="6"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="7"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="8"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="9"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- >
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- android:contentDescription="@string/keyboardview_keycode_delete"
- style="@style/NumPadKey.Delete"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="0"
- />
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- style="@style/NumPadKey.Enter"
- android:contentDescription="@string/keyboardview_keycode_enter"
- />
- </LinearLayout>
- </LinearLayout>
+ <androidx.constraintlayout.helper.widget.Flow
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/pukEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/pukEntry" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
<include layout="@layout/keyguard_eca"
android:id="@+id/keyguard_selector_fade_container"
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index ce88d5b..6a18b3d 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -31,8 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzea optimizatu da bateria ez kaltetzeko"</string>
- <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
- <skip />
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargagailua ez da bateragarria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ez dago SIMik"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 80bd0bf..2f295f7 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -31,8 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la pile"</string>
- <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
- <skip />
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • chargeur incompatible"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Aucune carte SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index b2058a1..9dd5c5d 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -31,8 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 보호를 위해 충전 최적화됨"</string>
- <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
- <skip />
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 호환되지 않는 충전기"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM 없음"</string>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 51f507c..11b4d79 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -56,7 +56,7 @@
<string name="keyguard_plugged_in_charging_limited"><xliff:g id="percentage">%s</xliff:g> • Charging optimized to protect battery</string>
<!-- When the lock screen is showing and the phone plugged in with incompatible charger. -->
- <string name="keyguard_plugged_in_incompatible_charger"><xliff:g id="percentage">%s</xliff:g> • Incompatible charging</string>
+ <string name="keyguard_plugged_in_incompatible_charger"><xliff:g id="percentage">%s</xliff:g> • Issue with charging accessory</string>
<!-- On the keyguard screen, when pattern lock is disabled, only tell them to press menu to unlock. This is shown in small font at the bottom. -->
<string name="keyguard_instructions_when_pattern_disabled">Press Menu to unlock.</string>
diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml
index 75c8286..a677c12 100644
--- a/packages/SystemUI/res-product/values/strings.xml
+++ b/packages/SystemUI/res-product/values/strings.xml
@@ -122,6 +122,12 @@
Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (tablet) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen.</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (device) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen.</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (default) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen.</string>
<!-- Text shown when viewing global actions while phone is locked and additional controls are hidden [CHAR LIMIT=NONE] -->
<string name="global_action_lock_message" product="default">Unlock your phone for more options</string>
@@ -134,4 +140,7 @@
<string name="media_transfer_playing_this_device" product="default">Playing on this phone</string>
<!-- Text informing the user that their media is now playing on this tablet device. [CHAR LIMIT=50] -->
<string name="media_transfer_playing_this_device" product="tablet">Playing on this tablet</string>
+
+
+
</resources>
diff --git a/packages/SystemUI/res/drawable/controls_panel_background.xml b/packages/SystemUI/res/drawable/controls_panel_background.xml
index 9092877..fc108a5 100644
--- a/packages/SystemUI/res/drawable/controls_panel_background.xml
+++ b/packages/SystemUI/res/drawable/controls_panel_background.xml
@@ -18,5 +18,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#1F1F1F" />
- <corners android:radius="@dimen/notification_corner_radius" />
+ <corners android:radius="@dimen/controls_panel_corner_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
new file mode 100644
index 0000000..2e29cae
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:inset="@dimen/qs_footer_action_inset">
+ <ripple
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <!-- We make this shape a rounded rectangle instead of a oval so that it can animate -->
+ <!-- properly into an app/dialog. -->
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/white"/>
+ <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+ </shape>
+ </item>
+
+ </ripple>
+</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_fullscreen.xml b/packages/SystemUI/res/layout/controls_fullscreen.xml
index e08e63b..fa70303 100644
--- a/packages/SystemUI/res/layout/controls_fullscreen.xml
+++ b/packages/SystemUI/res/layout/controls_fullscreen.xml
@@ -15,19 +15,11 @@
limitations under the License.
-->
-<FrameLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/control_detail_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/global_actions_controls"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingHorizontal="@dimen/controls_padding_horizontal" />
-
-</FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index aa211bf..71561c0 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -13,82 +13,94 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<merge
- xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:orientation="vertical"
+ tools:parentTag="android.widget.LinearLayout">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginBottom="@dimen/controls_header_bottom_margin">
-
- <!-- make sure the header stays centered in the layout by adding a spacer -->
- <Space
- android:id="@+id/controls_spacer"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="1dp"
- android:visibility="gone" />
-
- <ImageView
- android:id="@+id/controls_close"
- android:contentDescription="@string/accessibility_desc_close"
- android:src="@drawable/ic_close"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:tint="@color/control_primary_text"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="@dimen/controls_header_menu_size"
- android:padding="12dp"
- android:visibility="gone" />
- <!-- need to keep this outer view in order to have a correctly sized anchor
- for the dropdown menu, as well as dropdown background in the right place -->
<LinearLayout
- android:id="@+id/controls_header"
- android:orientation="horizontal"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:minHeight="48dp"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center">
- <TextView
- style="@style/Control.Spinner.Header"
- android:clickable="false"
- android:id="@+id/app_or_structure_spinner"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center" />
- </LinearLayout>
- <ImageView
- android:id="@+id/controls_more"
- android:src="@drawable/ic_more_vert"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="@dimen/controls_header_menu_size"
- android:padding="12dp"
- android:tint="@color/control_more_vert"
- android:layout_gravity="center"
- android:contentDescription="@string/accessibility_menu"
- android:background="?android:attr/selectableItemBackgroundBorderless" />
- </LinearLayout>
+ android:paddingHorizontal="@dimen/controls_header_horizontal_padding"
+ android:layout_marginBottom="@dimen/controls_header_bottom_margin"
+ android:orientation="horizontal">
- <ScrollView
+ <!-- make sure the header stays centered in the layout by adding a spacer -->
+ <Space
+ android:id="@+id/controls_spacer"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="1dp"
+ android:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/controls_close"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="@dimen/controls_header_menu_button_size"
+ android:layout_gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_desc_close"
+ android:padding="12dp"
+ android:src="@drawable/ic_close"
+ android:tint="@color/control_primary_text"
+ android:visibility="gone"
+ tools:visibility="visible" />
+
+ <!-- need to keep this outer view in order to have a correctly sized anchor
+ for the dropdown menu, as well as dropdown background in the right place -->
+ <LinearLayout
+ android:id="@+id/controls_header"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:minHeight="48dp"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/app_or_structure_spinner"
+ style="@style/Control.Spinner.Header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:clickable="false"
+ tools:text="Test app" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/controls_more"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="@dimen/controls_header_menu_button_size"
+ android:layout_gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_menu"
+ android:padding="12dp"
+ android:src="@drawable/ic_more_vert"
+ android:tint="@color/control_more_vert" />
+ </LinearLayout>
+
+ <ScrollView
android:id="@+id/controls_scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
+ android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
android:layout_weight="1"
- android:orientation="vertical"
android:clipChildren="true"
+ android:orientation="vertical"
android:paddingHorizontal="16dp"
android:scrollbars="none">
- <include layout="@layout/global_actions_controls_list_view" />
- </ScrollView>
+ <include layout="@layout/global_actions_controls_list_view" />
- <FrameLayout
- android:id="@+id/controls_panel"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:background="@drawable/controls_panel_background"
- android:visibility="gone"
- />
+ </ScrollView>
+
+ <FrameLayout
+ android:id="@+id/controls_panel"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/controls_panel_background"
+ android:visibility="gone"
+ tools:visibility="visible" />
</merge>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index b1d3ed05..745cfc6 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -64,7 +64,7 @@
android:layout_width="@dimen/qs_footer_action_button_size"
android:layout_height="@dimen/qs_footer_action_button_size"
android:layout_gravity="center_vertical|end"
- android:background="?android:attr/selectableItemBackground"
+ android:background="@drawable/qs_footer_edit_circle"
android:clickable="true"
android:contentDescription="@string/accessibility_quick_settings_edit"
android:focusable="true"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index be9ef9d..f265426 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kennisgewingskerm."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Vinnige instellings."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kitsinstellings en kennisgewingskerm."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sluitskerm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Werksluitskerm"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Maak toe"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 03925f7..4ec413e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مركز الإشعارات."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"الإعدادات السريعة."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"الإعدادات السريعة\" و\"مركز الإشعارات\""</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"شاشة القفل."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"شاشة قفل بيانات العمل"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"إغلاق"</string>
@@ -695,7 +694,7 @@
<string name="right_keycode" msgid="2480715509844798438">"رمز مفتاح اليمين"</string>
<string name="left_icon" msgid="5036278531966897006">"رمز اليسار"</string>
<string name="right_icon" msgid="1103955040645237425">"رمز اليمين"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة الميزات."</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة المربّعات"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات."</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"اسحب هنا للإزالة"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"الحدّ الأدنى من عدد المربعات الذي تحتاج إليه هو <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى الملف الشخصي للعمل"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"إغلاق"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"إعدادات شاشة القفل"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"لا يتوفّر اتصال Wi-Fi."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"استخدام الكاميرا محظور."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"استخدام الكاميرا والميكروفون محظور."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"استخدام الميكروفون محظور."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"وضع الأولوية مفعّل."</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"ميزة لفت انتباه \"مساعد Google\" مفعّلة."</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 9507cda..ae2f1e2 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"জাননী পেনেল।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিং।"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ক্ষিপ্ৰ ছেটিং জাননী পেনেল।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীন।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index fcee2e1..3349674 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildiriş kölgəsi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tez ayarlar."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Sürətli ayarlar və Bildiriş göstərişi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilid ekranı."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran kilidi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Qapadın"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 12ce259..dbfb012 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Цень апавяшчэння.."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Хуткія налады."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Хуткія налады і шчыток апавяшчэнняў."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блакіроўкі."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Экран блакіроўкі дзейнасці"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыць"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Пераключыцца на працоўны профіль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыць"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Налады экрана блакіроўкі"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Сетка Wi-Fi недаступная"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблакіравана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера і мікрафон заблакіраваны"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрафон заблакіраваны"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Прыярытэтны рэжым уключаны"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Памочнік гатовы выконваць каманды"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 9ba041e..e87b628 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Падащ панел с известия."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Бързи настройки."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Падащ панел с бързи настройки и известия."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заключване на екрана."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заключен екран на служебния профил"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затваряне"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index dbc3a52..2a84e59 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"বিজ্ঞপ্তি শেড৷"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"দ্রুত সেটিংস৷"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"দ্রুত সেটিংস এবং বিজ্ঞপ্তি শেড।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"লক স্ক্রিন।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কর্মস্থলের স্ক্রিন লক"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ করুন"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"অফিস প্রোফাইলে পাল্টে নিন"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ করুন"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্রিন সেটিংস"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ওয়াই-ফাই উপলভ্য নয়"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ক্যামেরার অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ক্যামেরা এবং মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\'প্রায়োরিটি\' মোড চালু করা আছে"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"অ্যাসিস্ট্যান্ট আপনার কথা শোনার জন্য চালু করা আছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 8d4a0dd..e73eab9 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -198,7 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obavještenja sa sjenčenjem."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
- <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i zaslon obavijesti."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i lokacija za obavještenja."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index cc87895..66d20e4 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Àrea de notificacions"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuració ràpida"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuració ràpida i àrea de notificacions."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueig"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueig per a la feina"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tanca"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Canvia al perfil de treball"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tanca"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configuració pantalla de bloqueig"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"No hi ha cap Wi‑Fi disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La càmera està bloquejada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La càmera i el micròfon estan bloquejats"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micròfon està bloquejat"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El mode Prioritat està activat"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'Assistent està activat"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e07a892..e61a4d0 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel oznámení."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rychlé nastavení."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rychlé nastavení a panel oznámení"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Obrazovka uzamčení"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Obrazovka uzamčení pracovního profilu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zavřít"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 4b10ddf..aa6a480 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notifikationspanel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kvikmenu."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kvikmenu og notifikationspanel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskærm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskærm til arbejde"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Luk"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skift til arbejdsprofil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Luk"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Indstillinger for låseskærm"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ikke tilgængeligt"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokeret"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Der er blokeret for kameraet og mikrofonen"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokeret"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetstilstand er aktiveret"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent lytter"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f8c02e3..621788a 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Benachrichtigungsleiste"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Schnelleinstellungen"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Schnelleinstellungen und Benachrichtigungsleiste."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sperrbildschirm"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Sperrbildschirm für Arbeitsprofil"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Schließen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f2fb5b8..d81cedb 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Γρήγορες ρυθμίσεις."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Γρήγορες ρυθμίσεις και πλαίσιο σκίασης ειδοποιήσεων."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Οθόνη κλειδώματος"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Οθόνη κλειδωμένης εργασίας"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Κλείσιμο"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 81682b5..44b56de 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida y panel de notificaciones."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla bloqueada del perfil de trabajo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Config. de pantalla de bloqueo"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi no disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La cámara está bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La cámara y el micrófono están bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micrófono está bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El modo de prioridad está activado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistente está prestando atención"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 526743a..9080c58 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ajustes rápidos"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ajustes rápidos y pantalla de notificaciones."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo para el perfil de trabajo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -1019,7 +1018,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ajustes de pantalla de bloqueo"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Red Wi-Fi no disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Cámara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Cámara y micrófono bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrófono bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridad activado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"El Asistente está activado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9388a14..9ce7dbf 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Märguande vari."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kiirseaded."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kiirseaded ja märguandeala."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kuva lukustamine."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Töö lukustuskuva"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sulgemine"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Lülitu tööprofiilile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Sule"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lukustuskuva seaded"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi pole saadaval"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kaamera on blokeeritud"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kaamera ja mikrofon on blokeeritud"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon on blokeeritud"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteetne režiim on sisse lülitatud"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent on aktiveeritud"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 84f2d0c..d37afba 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -616,84 +616,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Jakinarazpenak"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Lasterbideak"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu tekl. diseinua"</string>
- <!-- no translation found for keyboard_shortcut_clear_text (4679927133259287577) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
- <skip />
- <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
- <skip />
- <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
- <skip />
- <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
- <skip />
- <!-- no translation found for group_system_go_back (8838454003680364227) -->
- <skip />
- <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
- <skip />
- <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
- <skip />
- <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
- <skip />
- <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
- <skip />
- <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
- <skip />
- <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
- <skip />
- <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
- <skip />
- <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
- <skip />
- <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
- <skip />
- <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
- <skip />
- <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
- <skip />
- <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
- <skip />
- <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
- <skip />
- <!-- no translation found for system_multitasking_replace (844285282472557186) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
- <skip />
- <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
- <skip />
- <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
- <skip />
- <!-- no translation found for input_access_emoji (8105642858900406351) -->
- <skip />
- <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
- <skip />
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Garbitu testua"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lasterbideak"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Bilatu lasterbideak"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ez da aurkitu lasterbiderik"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Sarrera"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Irekitako aplikazioak"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Uneko aplikazioa"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Atzitu jakinarazpenen panela"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Atera pantaila osoaren argazki bat"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Atzitu sistemaren edo aplikazioetarako lasterbideen zerrenda"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Atzera: itzuli aurreko egoerara (atzera egiteko botoia)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Atzitu hasierako pantaila"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ikusi irekitako aplikazioen ikuspegi orokorra"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Joan azken aplikazioetako batetik bestera (aurrera)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Joan azken aplikazioetako batetik bestera (atzera)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Atzitu aplikazio guztien zerrenda eta bilatu (adibidez, bilatzeko aukeraren edo Exekutatzeko tresna aplikazioaren bidez)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ezkutatu eta erakutsi (berriro) zereginen barra"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Atzitu sistemaren ezarpenak"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Atzitu Google-ren Laguntzailea"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokeatu pantaila"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Ireki Oharrak aplikazioa oharrak bizkor idazteko"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Zereginen aldibereko sistemaren exekuzioa"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Sartu pantaila zatituaren eskuineko aldean uneko aplikazioarekin"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Sartu pantaila zatituaren ezkerreko aldean uneko aplikazioarekin"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Aldatu pantaila zatitutik pantaila osora"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Pantaila zatituan zaudela: ordeztu aplikazio bat beste batekin"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Sarrera"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Aldatu idazteko hizkuntza (hurrengo hizkuntza)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Aldatu idazteko hizkuntza (aurreko hizkuntza)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Atzitu emojiak"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Atzitu ahozko idazketa"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikazioak"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Laguntzailea"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Ireki arakatzailea (Chrome, modu lehenetsian)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktuak"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Ireki posta elektronikoa (Gmail, modu lehenetsian)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMSak"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musika"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Ireki Kalkulagailua"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Ireki Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ez molestatzeko modua"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Bolumen-botoietarako lasterbidea"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -856,12 +820,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"pantaila-grabaketa"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Egonean"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Letraren tamaina"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Txikitu"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Handitu"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Handitu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bafee64..9bc513e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مجموعه اعلان."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"تنظیمات سریع."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"تنظیمات فوری و کشوی اعلانات."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"صفحه قفل."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"صفحه قفل کاری"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"بستن"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4097e76..4c3962e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ilmoitusalue."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Pika-asetukset."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Pika-asetukset ja ilmoitusalue"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lukitse näyttö."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Työlukitusnäyttö"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sulje"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 47974b2..05dec17 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -616,84 +616,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Raccourcis clavier"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la disposition du clavier"</string>
- <!-- no translation found for keyboard_shortcut_clear_text (4679927133259287577) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
- <skip />
- <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
- <skip />
- <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
- <skip />
- <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
- <skip />
- <!-- no translation found for group_system_go_back (8838454003680364227) -->
- <skip />
- <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
- <skip />
- <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
- <skip />
- <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
- <skip />
- <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
- <skip />
- <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
- <skip />
- <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
- <skip />
- <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
- <skip />
- <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
- <skip />
- <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
- <skip />
- <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
- <skip />
- <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
- <skip />
- <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
- <skip />
- <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
- <skip />
- <!-- no translation found for system_multitasking_replace (844285282472557186) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
- <skip />
- <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
- <skip />
- <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
- <skip />
- <!-- no translation found for input_access_emoji (8105642858900406351) -->
- <skip />
- <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
- <skip />
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Effacer le texte"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Recherchez des raccourcis"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Aucun raccourci trouvé"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Système"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrée"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ouvrir applis"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Appli actuelle"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accéder au volet de notification"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Prendre une capture d\'écran complète"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accéder à la liste des raccourcis du système/des applications"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Retour : retour à l\'état précédent (bouton précédent)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accéder à l\'écran d\'accueil"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Aperçu des applications ouvertes"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Parcourir les applications récentes (avancer)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Parcourir les applications récentes (retour)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accéder à la liste des applis et à la recherche (recherche/lanceur)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Masquer et (ré)afficher la barre des tâches"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accéder aux paramètres système"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accéder à l\'Assistant Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Écran de verrouillage"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Ouvrir l\'application de prise de notes pour prendre des notes rapides"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Passer à l\'écran partagé avec l\'application actuelle à droite"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Passer à l\'écran partagé avec l\'application actuelle à gauche"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Passer de l\'écran partagé au plein écran"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"En mode d\'écran partagé : remplacer une application par une autre"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrée"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Changer la langue d\'entrée (langue suivante)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Changer la langue d\'entrée (langue précédente)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Accéder aux émojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Accéder à l\'entrée vocale"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistance"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navigateur (Chrome par défaut)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Courriel (Gmail par défaut)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Messages texte"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musique"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculatrice"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Raccourci des boutons de volume"</string>
<string name="battery" msgid="769686279459897127">"Pile"</string>
@@ -856,12 +820,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement d\'écran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Rapetisser"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Effectuer un zoom avant"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7e2bada..0e089c8 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Réglages rapides"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Réglages rapides et volet des notifications."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Écran de verrouillage du profil professionnel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Caméra bloquée"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Caméra et micro bloqués"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micro bloqué"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Prioritaire activé"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 8ff9b06..ea532f5 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel despregable"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida e panel despregable."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo do perfil de traballo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Pechar"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar ao perfil de traballo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Pechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configuración pantalla bloqueo"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi non dispoñible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"A cámara está bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"A cámara e o micrófono están bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"O micrófono está bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"O modo de prioridade está activado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"A atención do Asistente está activada"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index d1422ba..3f2b494 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"નોટિફિકેશન શેડ."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ઝડપી સેટિંગ."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ઝડપી સેટિંગ અને નોટિફિકેશન શેડ."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"લૉક સ્ક્રીન."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"કાર્ય લૉક સ્ક્રીન"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"બંધ કરો"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"બંધ કરો"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"લૉક સ્ક્રીનના સેટિંગ"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"કૅમેરા બ્લૉક કરેલો છે"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"કૅમેરા અને માઇક્રોફોન બ્લૉક કરેલા છે"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"માઇક્રોફોન બ્લૉક કરેલો છે"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"પ્રાધાન્યતા મોડ ચાલુ છે"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant સક્રિય છે"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 0d08dcd..c49861b 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"त्वरित सेटिंग."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग और नोटिफ़िकेशन शेड."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"वर्क लॉक स्क्रीन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करें"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index fadc88d..b9c6067 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Értesítési felület."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Gyorsbeállítások."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Gyorsbeállítások és értesítési terület"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lezárási képernyő."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Munka lezárási képernyővel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Bezárás"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Váltás munkaprofilra"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Bezárás"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lezárási képernyő beállításai"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Nem áll rendelkezésre Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera letiltva"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera és mikrofon letiltva"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon letiltva"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritás mód bekapcsolva"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"A Segéd figyel"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 22877cf..018120a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ծանուցումների վահանակ:"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Արագ կարգավորումներ:"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Արագ կարգավորումներ և ծանուցումների վահանակ։"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Էկրանի կողպում:"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Աշխատանքային պրոֆիլի կողպէկրան"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Փակել"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Անցնել աշխատանքային պրոֆիլ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Փակել"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Կողպէկրանի կարգավորումներ"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ցանց հասանելի չէ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Տեսախցիկն արգելափակված է"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Տեսախցիկն ու խոսափողը արգելափակված են"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Խոսափողն արգելափակված է"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Առաջնահերթության ռեժիմը միացված է"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Օգնականը լսում է"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 262d0e1..d76d2ff 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bayangan pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setelan cepat."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Setelan cepat dan Menu notifikasi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Layar kunci."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Layar kunci kantor"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Beralih ke profil kerja"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Setelan layar kunci"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera diblokir"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon diblokir"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon diblokir"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode prioritas diaktifkan"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asisten sedang memerhatikan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7bdc66c..2280524 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Tilkynningasvæði."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Flýtistillingar."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Flýtistillingar og tilkynningagluggi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lásskjár."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vinnulásskjár"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Loka"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skipta yfir í vinnusnið"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Loka"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Stillingar fyrir lásskjá"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ekki til staðar"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Lokað fyrir myndavél"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Lokað fyrir myndavél og hljóðnema"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Lokað fyrir hljóðnema"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Kveikt er á forgangsstillingu"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Hjálparinn er að hlusta"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index bc983ff..8731382 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1110,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa a profilo di lavoro"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Chiudi"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Impostazioni schermata di blocco"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponibile"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Videocamera bloccata"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Videocamera e microfono bloccati"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfono bloccato"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modalità priorità attivata"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'assistente è attivo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 859435f..8946db2 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"לוח התראות."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"הגדרות מהירות."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"הגדרות מהירות ולוח ההתראות."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"מסך נעילה."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"מסך נעילה של עבודה"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"סגירה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ca29664..d5b96d5 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知シェード"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"クイック設定"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"クイック設定と通知シェード。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ロック画面"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"仕事用プロファイルのロック画面"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"閉じる"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 4e40a73..54101b1 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"შეტყობინებების ფარდა"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"სწრაფი პარამეტრები"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"სწრაფი პარამეტრები და შეტყობინებების ფარდა"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ეკრანის დაბლოკვა."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"სამსახურის ჩაკეტილი ეკრანი"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"დახურვა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 459237b..dce96820 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Хабарландыру тақтасы"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Жылдам параметрлер."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Жылдам параметрлер мен хабарландыру тақтасы."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Бекіту экраны."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Әрекетті құлыптау экраны"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Жабу"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабу"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Экран құлпының параметрлері"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi қолжетімсіз."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгелген."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера мен микрофон бөгелген."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгелген."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\"Маңызды\" режимі қосулы."</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant қосулы."</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index f345283..ef20217 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ពណ៌ការជូនដំណឹង"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ការកំណត់រហ័ស។"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ការកំណត់រហ័ស និងផ្ទាំងជូនដំណឹង។"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ចាក់សោអេក្រង់។"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"អេក្រង់ចាក់សោលក្ខណៈការងារ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"បិទ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 6e22f36..c830e84 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳು."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಯ ಪರದೆ."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ಲಾಕ್ ಸ್ಕ್ರೀನ್."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ಕೆಲಸದ ಲಾಕ್ ಪರದೆ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f7a6dfb..b33168f 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"알림 세부정보"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"빠른 설정"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"빠른 설정 및 알림 창입니다."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"화면을 잠급니다."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"업무용 잠금 화면"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"닫기"</string>
@@ -616,84 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"알림"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"단축키"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"키보드 레이아웃 전환"</string>
- <!-- no translation found for keyboard_shortcut_clear_text (4679927133259287577) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
- <skip />
- <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
- <skip />
- <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
- <skip />
- <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
- <skip />
- <!-- no translation found for group_system_go_back (8838454003680364227) -->
- <skip />
- <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
- <skip />
- <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
- <skip />
- <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
- <skip />
- <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
- <skip />
- <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
- <skip />
- <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
- <skip />
- <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
- <skip />
- <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
- <skip />
- <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
- <skip />
- <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
- <skip />
- <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
- <skip />
- <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
- <skip />
- <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
- <skip />
- <!-- no translation found for system_multitasking_replace (844285282472557186) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
- <skip />
- <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
- <skip />
- <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
- <skip />
- <!-- no translation found for input_access_emoji (8105642858900406351) -->
- <skip />
- <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
- <skip />
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"텍스트 삭제"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"단축키"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"단축키 검색"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"단축키 없음"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"시스템"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"입력"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"열린 앱"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"현재 앱"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"알림 창에 액세스"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"전체 스크린샷 촬영"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"시스템/앱 단축키 목록에 액세스"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"뒤로: 이전 상태로 되돌아가기(뒤로 버튼)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"홈 화면에 액세스"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"열린 앱 개요"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"최근 앱 간 순환(앞으로)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"최근 앱 간 순환(뒤로)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"모든 앱 및 검색 목록(예: 검색/런처)에 액세스"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"태스크 바 숨김 및 다시 표시"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"시스템 설정에 액세스"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google 어시스턴트에 액세스"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"잠금 화면"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"빠른 메모를 위해 노트 앱 불러오기"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"시스템 멀티태스킹"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"현재 앱을 오른쪽으로 보내는 화면 분할 입력"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"현재 앱을 왼쪽으로 보내는 화면 분할 입력"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"화면 분할에서 전체 화면으로 전환"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"화면 분할 중: 다른 앱으로 바꾸기"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"입력"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"입력 언어 전환(다음 언어)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"입력 언어 전환(이전 언어)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"이모티콘에 액세스"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"음성 입력에 액세스"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"애플리케이션"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"지원"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"브라우저(Chrome을 기본값으로 설정)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"연락처"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"이메일(Gmail을 기본값으로 설정)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"음악"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"캘린더"</string>
- <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
- <skip />
- <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
- <skip />
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"계산기"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"지도"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"방해 금지 모드"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"볼륨 버튼 단축키"</string>
<string name="battery" msgid="769686279459897127">"배터리"</string>
@@ -856,12 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"화면 녹화"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"대기"</string>
- <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
- <skip />
- <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
- <skip />
- <!-- no translation found for font_scaling_larger (5476242157436806760) -->
- <skip />
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"글꼴 크기"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"축소"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"확대"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"확대"</string>
@@ -1150,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"직장 프로필로 전환"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"닫기"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"잠금 화면 설정"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi를 사용할 수 없음"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"카메라 차단됨"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"카메라 및 마이크 차단됨"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"마이크 차단됨"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"우선순위 모드 설정됨"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"어시스턴트가 대기 중임"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 3d6a949..d50e197 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Билдирмелер тактасы."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Тез тууралоолор."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ыкчам параметрлер жана билдирмелер тактасы."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Кулпуланган экран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Жумуштун кулпуланган экраны"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Жабуу"</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index bc63c9f..4f38e60 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -64,5 +64,6 @@
<dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
- <dimen name="controls_padding_horizontal">16dp</dimen>
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
+ <dimen name="controls_content_margin_horizontal">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 0b5b5de..4161049 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ໜ້າຈໍແຈ້ງເຕືອນ."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ການຕັ້ງຄ່າດ່ວນ."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ການຕັ້ງຄ່າດ່ວນ ແລະ ເງົາການແຈ້ງເຕືອນ."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ລັອກໜ້າຈໍ."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ໜ້າຈໍລັອກວຽກ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ປິດ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d607b17..b374789 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pranešimų gaubtas."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Spartieji nustatymai."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Spartieji nustatymai ir pranešimų skydelis."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Užrakinimo ekranas."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darbo profilio užrakinimo ekranas"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Uždaryti"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 30ffd4b..f82bcd6 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Paziņojumu panelis"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ātrie iestatījumi"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ātrie iestatījumi un paziņojumu panelis."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Bloķēšanas ekrāns."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darba profila bloķēšanas ekrāns"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Aizvērt"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pārslēgties uz darba profilu"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Aizvērt"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Bloķēšanas ekrāna iestatījumi"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nav pieejams"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera ir bloķēta"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameras un mikrofona lietošana ir bloķēta"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofons ir bloķēts"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritātes režīms ir ieslēgts"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistents klausās"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index cda4a85..64631c8 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панел за известување"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брзи поставки."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"„Брзи поставки“ и „Панел со известувања“."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заклучи екран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Работен заклучен екран"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Префрли се на работен профил"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Поставки за заклучен екран"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е достапно"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерата е блокирана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камерата и микрофонот се блокирани"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофонот е блокиран"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетниот режим е вклучен"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Вниманието на „Помошникот“ е вклучено"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 5802410..75633a2 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"അറിയിപ്പ് ഷെയ്ഡ്."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ദ്രുത ക്രമീകരണങ്ങൾ."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"അറിയിപ്പ് ഷെയ്ഡിനുള്ള ദ്രുത ക്രമീകരണം."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ലോക്ക് സ്ക്രീൻ."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ഔദ്യോഗിക ലോക്ക് സ്ക്രീൻ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"അവസാനിപ്പിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 3e6405c..c1be9f7 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Мэдэгдлийн хураангуй самбар"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Шуурхай тохиргоо."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Шуурхай тохиргоо болон мэдэгдлийн хураангуй самбар."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Дэлгэц түгжих."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ажлын түгжигдсэн дэлгэц"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Хаах"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f582a9f..b729efc 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"क्विक सेटिंग्ज."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग्ज आणि सूचना शेड."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य लॉक स्क्रीन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करा"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइलवर स्विच करा"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करा"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन सेटिंग्ज"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाय-फाय उपलब्ध नाही"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कॅमेरा ब्लॉक केला"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कॅमेरा आणि मायक्रोफोन ब्लॉक केले आहेत"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"मायक्रोफोन ब्लॉक केला"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राधान्य मोड सुरू आहे"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant चे लक्ष हे आता अॅक्टिव्ह आहे"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 4624a4ba..9ed0636 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bidai pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tetapan pantas."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tetapan pantas dan Bidai pemberitahuan."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kunci skrin."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrin kunci kerja"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 6463480..88165a8 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"အကြောင်းကြားစာအကွက်"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"အမြန်လုပ် အပြင်အဆင်"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‘အမြန်ဆက်တင်များ’ နှင့် ‘အကြောင်းကြားစာအကွက်’။"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"မျက်နှာပြင် သော့ပိတ်ရန်"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"အလုပ်သုံး လော့ခ်မျက်နှာပြင်"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ပိတ်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 94ebf2b..33d87ea 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Varselskygge."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hurtiginnstillinger."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hurtiginnstillinger og varselpanelet"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskjerm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskjerm for arbeid"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Lukk"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d16e91f..48e134b 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना कक्ष।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"द्रुत सेटिङहरू"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"द्रुत सेटिङ तथा सूचना कक्ष।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"स्क्रीन बन्द गर्नुहोस्।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य प्रोफाइलको लक स्क्रिन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बन्द गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 995abb0..2f86231 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meldingenpaneel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snelle instellingen."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snelle instellingen en meldingenpaneel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Vergrendelscherm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vergrendelscherm voor werk"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sluiten"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index f1b69b4..4ac1f84 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ବିଜ୍ଞପ୍ତି ଶେଡ୍।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"କ୍ୱିକ୍ ସେଟିଂସ୍।"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"କୁଇକ ସେଟିଂସ ଏବଂ ବିଜ୍ଞପ୍ତି ସେଡ।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ଲକ୍ ସ୍କ୍ରୀନ୍।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ୱର୍କ ଲକ୍ ସ୍କ୍ରୀନ୍"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ବନ୍ଦ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 0c7708f..2360930 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ।"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">" ਲਾਕ ਸਕ੍ਰੀਨ।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ਕਾਰਜ-ਸਥਾਨ ਲਾਕ ਸਕ੍ਰੀਨ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ਬੰਦ ਕਰੋ"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਜਾਓ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ਬੰਦ ਕਰੋ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ਕੈਮਰਾ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤੇ ਗਏ"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ਤਰਜੀਹ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ਧਿਆਨ ਸੁਵਿਧਾ ਨੂੰ ਚਾਲੂ ਹੈ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 611e996..18450ab 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obszar powiadomień."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Szybkie ustawienia."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Szybkie ustawienia i obszar powiadomień."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekran blokady."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran blokady wyświetlany podczas działania"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zamknij"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Przełącz na profil służbowy"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zamknij"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ustawienia ekranu blokady"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Sieć Wi-Fi jest niedostępna"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera jest zablokowana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon są zablokowane"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon jest zablokowany"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tryb priorytetowy jest włączony"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asystent jest aktywny"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 105031c..8add565 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8145483..f8a684c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Painel de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Definições rápidas."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Definições rápidas e painel de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecrã de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecrã de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 105031c..8add565 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0303e64..a4698d6 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Fereastră pentru notificări."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setări rapide."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Fereastră de Setări rapide și notificări."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecranul de blocare."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecran de blocare pentru serviciu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Închide"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9a71eea..32a784c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель уведомлений"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Быстрые настройки"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Быстрые настройки и панель уведомлений."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блокировки."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заблокировано"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыть"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index ba04fab..8bb334e 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"දැනුම්දීම් ආවරණය."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ක්ෂණික සැකසීම්."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ඉක්මන් සැකසීම් සහ දැනුම්දීම් ඡායිතය."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"අගුළු තිරය."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"කාර්යාල අගුලු තිරය"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"වසන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 36058de..f418154 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel upozornení."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rýchle nastavenia."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rýchle nastavenia a panel upozornení"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Uzamknutá obrazovka"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Uzamknutá obrazovka pracovného profilu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zavrieť"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f4ae067..3bc8351 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon z obvestili."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hitre nastavitve."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hitre nastavitve in zaslon z obvestili"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaklenjen zaslon"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaklenjen zaslon delovnega profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zapri"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index f69221a..6a35e38e 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Streha e njoftimeve."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cilësimet e shpejta."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"Cilësimet e shpejta\" dhe \"Streha e njoftimeve\"."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekrani i kyçjes."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekrani i kyçjes së punës"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Mbylle"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 19e5952..8dcf0cd 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meddelandepanel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snabbinställningar."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snabbinställningar och meddelandepanel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låsskärm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låsskärm för arbete"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Stäng"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 1cfa514..49d4733 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kivuli cha arifa."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mipangilio ya haraka."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mipangilio ya haraka na Sehemu ya arifa."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Skrini iliyofungwa."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrini iliyofungwa ya kazini"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Funga"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Tumia wasifu wa kazini"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Funga"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Mipangilio ya skrini iliyofungwa"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi haipatikani"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera imezuiwa"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera na maikrofoni zimezuiwa"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Maikrofoni imezuiwa"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Hali ya kipaumbele imewashwa"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Programu ya Mratibu imewashwa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 7cd1470..59becc6 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -87,4 +87,7 @@
<!-- Biometric Auth pattern view size, better to align keyguard_security_width -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
+
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
+ <dimen name="controls_content_margin_horizontal">24dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 9ed9360..8583f05 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -37,6 +37,8 @@
<dimen name="qs_media_rec_album_size">112dp</dimen>
<dimen name="qs_media_rec_album_side_margin">16dp</dimen>
+ <dimen name="controls_panel_corner_radius">40dp</dimen>
+
<dimen name="lockscreen_shade_max_over_scroll_amount">42dp</dimen>
<!-- Roughly the same distance as media on LS to media on QS. We will translate by this value
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
index 8b41a44..9248d58 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -33,5 +33,7 @@
side -->
<dimen name="qs_tiles_page_horizontal_margin">60dp</dimen>
+ <dimen name="controls_panel_corner_radius">46dp</dimen>
+
<dimen name="notification_section_divider_height">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 8f59df6..2086459 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -19,7 +19,8 @@
<!-- gap on either side of status bar notification icons -->
<dimen name="status_bar_icon_padding">1dp</dimen>
- <dimen name="controls_padding_horizontal">40dp</dimen>
+ <dimen name="controls_header_horizontal_padding">28dp</dimen>
+ <dimen name="controls_content_margin_horizontal">40dp</dimen>
<dimen name="large_screen_shade_header_height">56dp</dimen>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a29df59..4a0cb46 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"నోటిఫికేషన్ షేడ్."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"శీఘ్ర సెట్టింగ్లు."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"క్విక్ సెట్టింగ్లు, నోటిఫికేషన్ తెర."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"లాక్ స్క్రీన్."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"కార్యాలయ లాక్ స్క్రీన్"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"మూసివేస్తుంది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f0a2123..64a5280 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1110,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"สลับไปใช้โปรไฟล์งาน"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ปิด"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"การตั้งค่าหน้าจอล็อก"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ไม่พร้อมใช้งาน"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"กล้องถูกบล็อกอยู่"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"กล้องและไมโครโฟนถูกบล็อกอยู่"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ไมโครโฟนถูกบล็อกอยู่"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"โหมดลำดับความสำคัญเปิดอยู่"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"การเรียกใช้งาน Assistant เปิดอยู่"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 05f4628..d4d583f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mga mabilisang setting."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mga mabilisang setting at Notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Lock screen sa trabaho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Isara"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 81f8486..4df50fc 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildirim gölgesi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hızlı ayarlar."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hızlı ayarlar ve Bildirim gölgesi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilit ekranı"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"İş profili kilit ekranı"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Kapat"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 3ba43d5..c24f858 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель сповіщень."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Швидке налаштування."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Швидкі налаштування й панель сповіщень."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заблокований екран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Екран блокування завдання"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрити"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в робочий профіль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрити"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Параметри заблокованого екрана"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Мережа Wi-Fi недоступна"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камеру заблоковано"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камеру й мікрофон заблоковано"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрофон заблоковано"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим пріоритету ввімкнено"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Асистента активовано"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 5388be5..17ff36b 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"اطلاعاتی شیڈ۔"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"فوری ترتیبات۔"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"فوری ترتیبات اور اطلاعاتی شیڈ۔"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"مقفل اسکرین۔"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"دفتری مقفل اسکرین"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"بند کریں"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d97be06..0b488f8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bóng thông báo."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cài đặt nhanh."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Cài đặt nhanh và ngăn thông báo."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Màn hình khóa."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Màn hình khóa công việc"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Đóng"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Chuyển sang hồ sơ công việc"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Đóng"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Cài đặt màn hình khoá"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Không có Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Máy ảnh bị chặn"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Máy ảnh và micrô bị chặn"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrô bị chặn"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Chế độ ưu tiên đang bật"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Trợ lý đang bật"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ea1c94a..b5d0e01 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知栏。"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷设置。"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快捷设置和通知栏。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"锁定屏幕。"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作锁定屏幕"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"关闭"</string>
@@ -1019,7 +1018,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"暂时已连接"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暂时连接"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"连接状况不佳"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"系统将不会自动连接到移动数据网络"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"无网络连接"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index cfd1cc8..cacf205 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快速設定。"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"上鎖畫面。"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作螢幕鎖定"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 450a3cc..3fbdd48 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷設定。"</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"螢幕鎖定。"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work 螢幕鎖定"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 85854c5..8039ca1 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -198,8 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Umthunzi wesaziso."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Izilingiselelo ezisheshayo."</string>
- <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
- <skip />
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Amasethingi asheshayo Nomthunzi wezaziso."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Khiya isikrini."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ukukhiya isikrini somsebenzi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Vala"</string>
@@ -1111,16 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Shintshela kuphrofayela yomsebenzi"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Vala"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Amasethingi okukhiya isikrini"</string>
- <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
- <skip />
- <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
- <skip />
- <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
- <skip />
- <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
- <skip />
- <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
- <skip />
- <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
- <skip />
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"I-Wi-Fi ayitholakali"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Ikhamera ivinjiwe"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Ikhamera nemakrofoni zivinjiwe"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Imakrofoni ivinjiwe"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imodi ebalulekile ivuliwe"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Ukunaka kwe-Assistant kuvuliwe"</string>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 738cfd7..e65c327 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -500,8 +500,8 @@
space -->
<bool name="config_showBatteryEstimateQSBH">false</bool>
- <!-- Whether to show a severe low battery dialog. -->
- <bool name="config_severe_battery_dialog">false</bool>
+ <!-- Whether to show extra battery saver confirmation dialog. -->
+ <bool name="config_extra_battery_saver_confirmation">false</bool>
<!-- A path representing a shield. Will sometimes be displayed with the battery icon when
needed. This path is a 10px wide and 13px tall. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 76f6f8a..aba3fc4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -573,7 +573,7 @@
<dimen name="qs_tile_margin_horizontal">8dp</dimen>
<dimen name="qs_tile_margin_vertical">@dimen/qs_tile_margin_horizontal</dimen>
<dimen name="qs_tile_margin_top_bottom">4dp</dimen>
- <dimen name="qs_brightness_margin_top">12dp</dimen>
+ <dimen name="qs_brightness_margin_top">8dp</dimen>
<dimen name="qs_brightness_margin_bottom">16dp</dimen>
<dimen name="qqs_layout_margin_top">16dp</dimen>
<dimen name="qqs_layout_padding_bottom">24dp</dimen>
@@ -625,7 +625,7 @@
<dimen name="qs_header_row_min_height">48dp</dimen>
<dimen name="qs_header_non_clickable_element_height">24dp</dimen>
- <dimen name="new_qs_header_non_clickable_element_height">20dp</dimen>
+ <dimen name="new_qs_header_non_clickable_element_height">24dp</dimen>
<dimen name="qs_footer_padding">20dp</dimen>
<dimen name="qs_security_footer_height">88dp</dimen>
@@ -1192,11 +1192,13 @@
<!-- Home Controls -->
<dimen name="controls_header_menu_size">48dp</dimen>
+ <dimen name="controls_header_menu_button_size">48dp</dimen>
<dimen name="controls_header_bottom_margin">16dp</dimen>
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
<dimen name="controls_header_app_icon_size">24dp</dimen>
<dimen name="controls_top_margin">48dp</dimen>
- <dimen name="controls_padding_horizontal">0dp</dimen>
- <dimen name="control_header_text_size">20sp</dimen>
+ <dimen name="controls_content_margin_horizontal">0dp</dimen>
+ <dimen name="control_header_text_size">24sp</dimen>
<dimen name="control_item_text_size">16sp</dimen>
<dimen name="control_menu_item_text_size">16sp</dimen>
<dimen name="control_menu_item_min_height">56dp</dimen>
@@ -1227,6 +1229,8 @@
<item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">1.0</item>
<dimen name="controls_task_view_right_margin">0dp</dimen>
+ <dimen name="controls_panel_corner_radius">42dp</dimen>
+
<!-- Home Controls activity view detail panel-->
<dimen name="controls_activity_view_corner_radius">@*android:dimen/config_bottomDialogCornerRadius</dimen>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 6354752..763930d 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -30,9 +30,6 @@
<bool name="flag_charging_ripple">false</bool>
- <!-- Whether to show chipbar UI whenever the device is unlocked by ActiveUnlock. -->
- <bool name="flag_active_unlock_chipbar">true</bool>
-
<!-- Whether the user switcher chip shows in the status bar. When true, the multi user
avatar will no longer show on the lockscreen -->
<bool name="flag_user_switcher_chip">false</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7b3caff..4d989a6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -407,8 +407,6 @@
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
- <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
<string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
@@ -2431,6 +2429,10 @@
panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=NONE] -->
<string name="controls_panel_authorization">When you add <xliff:g id="appName" example="My app">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here.</string>
+ <!-- Shows in a dialog presented to the user to authorize this app removal from a Device
+ controls panel [CHAR LIMIT=NONE] -->
+ <string name="controls_panel_remove_app_authorization">Remove controls for <xliff:g example="My app" id="appName">%s</xliff:g>?</string>
+
<!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] -->
<string name="accessibility_control_favorite">Favorited</string>
<!-- a11y state description for a control that is currently favorited with its position [CHAR LIMIT=NONE] -->
@@ -2471,6 +2473,8 @@
<string name="controls_dialog_title">Add to device controls</string>
<!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
<string name="controls_dialog_ok">Add</string>
+ <!-- Controls dialog remove app from a panel [CHAR LIMIT=40] -->
+ <string name="controls_dialog_remove">Remove</string>
<!-- Controls dialog message. Indicates app that suggested this control [CHAR LIMIT=NONE] -->
<string name="controls_dialog_message">Suggested by <xliff:g id="app" example="System UI">%s</xliff:g></string>
<!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
@@ -2588,6 +2592,8 @@
<string name="controls_menu_edit">Edit controls</string>
<!-- Controls menu, add another app [CHAR LIMIT=30] -->
<string name="controls_menu_add_another_app">Add app</string>
+ <!-- Controls menu, remove app [CHAR_LIMIT=30] -->
+ <string name="controls_menu_remove">Remove app</string>
<!-- Title for the media output dialog with media related devices [CHAR LIMIT=50] -->
<string name="media_output_dialog_add_output">Add outputs</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
index 12e0b9a..c5979cc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
@@ -65,35 +65,40 @@
} else {
1
}
- viewsToTranslate.forEach { (view, direction, shouldBeAnimated) ->
- if (shouldBeAnimated()) {
- view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
- }
+ viewsToTranslate.forEach { (view, direction) ->
+ view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
}
}
/** Finds in [parent] all views specified by [ids] and register them for the animation. */
private fun registerViewsForAnimation(parent: ViewGroup, ids: Set<ViewIdToTranslate>) {
viewsToTranslate =
- ids.mapNotNull { (id, dir, pred) ->
- parent.findViewById<View>(id)?.let { view ->
- ViewToTranslate(WeakReference(view), dir, pred)
+ ids.asSequence()
+ .filter { it.shouldBeAnimated() }
+ .mapNotNull {
+ parent.findViewById<View>(it.viewId)?.let { view ->
+ ViewToTranslate(WeakReference(view), it.direction)
+ }
}
- }
+ .toList()
}
- /** Represents a view to animate. [rootView] should contain a view with [viewId] inside. */
+ /**
+ * Represents a view to animate. [rootView] should contain a view with [viewId] inside.
+ * [shouldBeAnimated] is only evaluated when the viewsToTranslate is registered in
+ * [registerViewsForAnimation].
+ */
data class ViewIdToTranslate(
val viewId: Int,
val direction: Direction,
val shouldBeAnimated: () -> Boolean = { true }
)
- private data class ViewToTranslate(
- val view: WeakReference<View>,
- val direction: Direction,
- val shouldBeAnimated: () -> Boolean
- )
+ /**
+ * Represents a view whose animation process is in-progress. It should be immutable because the
+ * started animation should be completed.
+ */
+ private data class ViewToTranslate(val view: WeakReference<View>, val direction: Direction)
/** Direction of the animation. */
enum class Direction(val multiplier: Float) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
index 23742c5..454294f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
@@ -87,7 +87,7 @@
* Helper for evaluating 3-valued logical AND/OR.
*
* @param returnValueIfAnyMatches AND returns false if any value is false. OR returns true if
- * any value is true.
+ * any value is true.
*/
private fun threeValuedAndOrOr(
conditions: Collection<Condition>,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index ae68618..44f9d43 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,30 +16,9 @@
package com.android.systemui.shared.system;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.view.RemoteAnimationTarget.MODE_CHANGING;
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
-import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
-import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
-
-import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.WindowConfiguration;
-import android.graphics.Rect;
import android.util.ArrayMap;
-import android.util.SparseBooleanArray;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import android.view.WindowManager;
import android.window.TransitionInfo;
import android.window.TransitionInfo.Change;
@@ -53,156 +32,6 @@
*/
public class RemoteAnimationTargetCompat {
- private static int newModeToLegacyMode(int newMode) {
- switch (newMode) {
- case WindowManager.TRANSIT_OPEN:
- case WindowManager.TRANSIT_TO_FRONT:
- return MODE_OPENING;
- case WindowManager.TRANSIT_CLOSE:
- case WindowManager.TRANSIT_TO_BACK:
- return MODE_CLOSING;
- default:
- return MODE_CHANGING;
- }
- }
-
- /**
- * Almost a copy of Transitions#setupStartState.
- * TODO: remove when there is proper cross-process transaction sync.
- */
- @SuppressLint("NewApi")
- private static void setupLeash(@NonNull SurfaceControl leash,
- @NonNull TransitionInfo.Change change, int layer,
- @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
- final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
- // Put animating stuff above this line and put static stuff below it.
- int zSplitLine = info.getChanges().size();
- // changes should be ordered top-to-bottom in z
- final int mode = change.getMode();
-
- t.reparent(leash, info.getRootLeash());
- final Rect absBounds =
- (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
- t.setPosition(leash, absBounds.left - info.getRootOffset().x,
- absBounds.top - info.getRootOffset().y);
-
- // Put all the OPEN/SHOW on top
- if (TransitionUtil.isOpeningType(mode)) {
- if (isOpening) {
- t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
- if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
- // if transferred, it should be left visible.
- t.setAlpha(leash, 0.f);
- }
- } else {
- // put on bottom and leave it visible
- t.setLayer(leash, zSplitLine - layer);
- }
- } else if (TransitionUtil.isClosingType(mode)) {
- if (isOpening) {
- // put on bottom and leave visible
- t.setLayer(leash, zSplitLine - layer);
- } else {
- // put on top
- t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
- }
- } else { // CHANGE
- t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
- }
- }
-
- @SuppressLint("NewApi")
- private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
- int order, SurfaceControl.Transaction t) {
- // TODO: once we can properly sync transactions across process, then get rid of this leash.
- if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
- // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
- // making leashes means we have to handle them specially.
- return change.getLeash();
- }
- SurfaceControl leashSurface = new SurfaceControl.Builder()
- .setName(change.getLeash().toString() + "_transition-leash")
- .setContainerLayer()
- // Initial the surface visible to respect the visibility of the original surface.
- .setHidden(false)
- .setParent(info.getRootLeash())
- .build();
- // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
- setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
- t.reparent(change.getLeash(), leashSurface);
- t.setAlpha(change.getLeash(), 1.0f);
- t.show(change.getLeash());
- t.setPosition(change.getLeash(), 0, 0);
- t.setLayer(change.getLeash(), 0);
- return leashSurface;
- }
-
- /**
- * Creates a new RemoteAnimationTarget from the provided change info
- */
- public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
- TransitionInfo info, SurfaceControl.Transaction t,
- @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- final SurfaceControl leash = createLeash(info, change, order, t);
- if (leashMap != null) {
- leashMap.put(change.getLeash(), leash);
- }
- return newTarget(change, order, leash);
- }
-
- /**
- * Creates a new RemoteAnimationTarget from the provided change and leash
- */
- public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
- SurfaceControl leash) {
- int taskId;
- boolean isNotInRecents;
- ActivityManager.RunningTaskInfo taskInfo;
- WindowConfiguration windowConfiguration;
-
- taskInfo = change.getTaskInfo();
- if (taskInfo != null) {
- taskId = taskInfo.taskId;
- isNotInRecents = !taskInfo.isRunning;
- windowConfiguration = taskInfo.configuration.windowConfiguration;
- } else {
- taskId = INVALID_TASK_ID;
- isNotInRecents = true;
- windowConfiguration = new WindowConfiguration();
- }
-
- Rect localBounds = new Rect(change.getEndAbsBounds());
- localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
-
- RemoteAnimationTarget target = new RemoteAnimationTarget(
- taskId,
- newModeToLegacyMode(change.getMode()),
- // TODO: once we can properly sync transactions across process,
- // then get rid of this leash.
- leash,
- (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
- null,
- // TODO(shell-transitions): we need to send content insets? evaluate how its used.
- new Rect(0, 0, 0, 0),
- order,
- null,
- localBounds,
- new Rect(change.getEndAbsBounds()),
- windowConfiguration,
- isNotInRecents,
- null,
- new Rect(change.getStartAbsBounds()),
- taskInfo,
- change.getAllowEnterPip(),
- (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
- ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
- );
- target.setWillShowImeOnTarget(
- (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
- target.setRotationChange(change.getEndRotation() - change.getStartRotation());
- return target;
- }
-
/**
* Represents a TransitionInfo object as an array of old-style app targets
*
@@ -211,7 +40,7 @@
*/
public static RemoteAnimationTarget[] wrapApps(TransitionInfo info,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- return wrap(info, t, leashMap, new LeafTaskFilter());
+ return wrap(info, t, leashMap, new TransitionUtil.LeafTaskFilter());
}
/**
@@ -224,8 +53,8 @@
*/
public static RemoteAnimationTarget[] wrapNonApps(TransitionInfo info, boolean wallpapers,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- return wrap(info, t, leashMap, (change) ->
- (wallpapers ? isWallpaper(change) : isNonApp(change)));
+ return wrap(info, t, leashMap, (change) -> (wallpapers
+ ? TransitionUtil.isWallpaper(change) : TransitionUtil.isNonApp(change)));
}
private static RemoteAnimationTarget[] wrap(TransitionInfo info,
@@ -235,45 +64,10 @@
for (int i = 0; i < info.getChanges().size(); i++) {
TransitionInfo.Change change = info.getChanges().get(i);
if (filter.test(change)) {
- out.add(newTarget(change, info.getChanges().size() - i, info, t, leashMap));
+ out.add(TransitionUtil.newTarget(
+ change, info.getChanges().size() - i, info, t, leashMap));
}
}
return out.toArray(new RemoteAnimationTarget[out.size()]);
}
-
- /** Returns `true` if `change` is a wallpaper. */
- public static boolean isWallpaper(Change change) {
- return (change.getTaskInfo() == null)
- && change.hasFlags(FLAG_IS_WALLPAPER)
- && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
- }
-
- /** Returns `true` if `change` is not an app window or wallpaper. */
- public static boolean isNonApp(Change change) {
- return (change.getTaskInfo() == null)
- && !change.hasFlags(FLAG_IS_WALLPAPER)
- && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
- }
-
- /**
- * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
- * MUST call `test` in the same order that the changes appear in the TransitionInfo.
- */
- public static class LeafTaskFilter implements Predicate<Change> {
- private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
-
- @Override
- public boolean test(Change change) {
- final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- // Children always come before parent since changes are in top-to-bottom z-order.
- if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
- // has children, so not a leaf. Skip.
- return false;
- }
- if (taskInfo.hasParentTask()) {
- mChildTaskTargets.put(taskInfo.parentTaskId, true);
- }
- return true;
- }
- }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 70a36ce..fca55b1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -21,8 +21,6 @@
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.newTarget;
-
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -45,7 +43,6 @@
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
@@ -58,7 +55,7 @@
/** Constructor specifically for recents animation */
public static RemoteTransition newRemoteTransition(RecentsAnimationListener recents,
- RecentsAnimationControllerCompat controller, IApplicationThread appThread) {
+ IApplicationThread appThread) {
IRemoteTransition remote = new IRemoteTransition.Stub() {
final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
IBinder mToken = null;
@@ -69,7 +66,7 @@
IRemoteTransitionFinishedCallback finishedCallback) {
// TODO(b/177438007): Move this set-up logic into launcher's animation impl.
mToken = transition;
- mRecentsSession.start(controller, recents, mToken, info, t, finishedCallback);
+ mRecentsSession.start(recents, mToken, info, t, finishedCallback);
}
@Override
@@ -98,9 +95,8 @@
* TODO(b/177438007): Remove this once Launcher handles shell transitions directly.
*/
@VisibleForTesting
- static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
+ static class RecentsControllerWrap extends IRecentsAnimationController.Default {
private RecentsAnimationListener mListener = null;
- private RecentsAnimationControllerCompat mWrapped = null;
private IRemoteTransitionFinishedCallback mFinishCB = null;
/**
@@ -137,7 +133,7 @@
/** The latest state that the recents animation is operating in. */
private int mState = STATE_NORMAL;
- void start(RecentsAnimationControllerCompat wrapped, RecentsAnimationListener listener,
+ void start(RecentsAnimationListener listener,
IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
IRemoteTransitionFinishedCallback finishedCallback) {
if (mInfo != null) {
@@ -145,7 +141,6 @@
+ " recents is already active.");
}
mListener = listener;
- mWrapped = wrapped;
mInfo = info;
mFinishCB = finishedCallback;
mPausingTasks = new ArrayList<>();
@@ -160,16 +155,15 @@
final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
- RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
- new RemoteAnimationTargetCompat.LeafTaskFilter();
+ TransitionUtil.LeafTaskFilter leafTaskFilter = new TransitionUtil.LeafTaskFilter();
// About layering: we divide up the "layer space" into 3 regions (each the size of
// the change count). This lets us categorize things into above/below/between
// while maintaining their relative ordering.
for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change change = info.getChanges().get(i);
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (RemoteAnimationTargetCompat.isWallpaper(change)) {
- final RemoteAnimationTarget target = newTarget(change,
+ if (TransitionUtil.isWallpaper(change)) {
+ final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
// wallpapers go into the "below" layer space
info.getChanges().size() - i, info, t, mLeashMap);
wallpapers.add(target);
@@ -177,7 +171,7 @@
t.setAlpha(target.leash, 1);
} else if (leafTaskFilter.test(change)) {
// start by putting everything into the "below" layer space.
- final RemoteAnimationTarget target = newTarget(change,
+ final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
info.getChanges().size() - i, info, t, mLeashMap);
apps.add(target);
if (TransitionUtil.isClosingType(change.getMode())) {
@@ -203,7 +197,8 @@
}
}
t.apply();
- mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]),
+ mListener.onAnimationStart(new RecentsAnimationControllerCompat(this),
+ apps.toArray(new RemoteAnimationTarget[apps.size()]),
wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
new Rect(0, 0, 0, 0), new Rect());
}
@@ -217,8 +212,8 @@
TransitionInfo.Change recentsOpening = null;
boolean foundRecentsClosing = false;
boolean hasChangingApp = false;
- final RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
- new RemoteAnimationTargetCompat.LeafTaskFilter();
+ final TransitionUtil.LeafTaskFilter leafTaskFilter =
+ new TransitionUtil.LeafTaskFilter();
for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change change = info.getChanges().get(i);
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
@@ -246,6 +241,13 @@
closingTasks.add(change);
}
} else if (change.getMode() == TRANSIT_CHANGE) {
+ // Finish recents animation if the display is changed, so the default
+ // transition handler can play the animation such as rotation effect.
+ if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) {
+ mListener.onSwitchToScreenshot(() -> finish(false /* toHome */,
+ false /* userLeaveHint */));
+ return false;
+ }
hasChangingApp = true;
}
}
@@ -301,7 +303,8 @@
int pausingIdx = TaskState.indexOf(mPausingTasks, change);
if (pausingIdx >= 0) {
// Something is showing/opening a previously-pausing app.
- targets[i] = newTarget(change, layer, mPausingTasks.get(pausingIdx).mLeash);
+ targets[i] = TransitionUtil.newTarget(change, layer,
+ mPausingTasks.get(pausingIdx).mLeash);
mOpeningTasks.add(mPausingTasks.remove(pausingIdx));
// Setup hides opening tasks initially, so make it visible again (since we
// are already showing it).
@@ -309,7 +312,7 @@
t.setAlpha(change.getLeash(), 1.f);
} else {
// We are receiving new opening tasks, so convert to onTasksAppeared.
- targets[i] = newTarget(change, layer, info, t, mLeashMap);
+ targets[i] = TransitionUtil.newTarget(change, layer, info, t, mLeashMap);
t.reparent(targets[i].leash, mInfo.getRootLeash());
t.setLayer(targets[i].leash, layer);
mOpeningTasks.add(new TaskState(change, targets[i].leash));
@@ -337,13 +340,9 @@
}
}
- @Override public ThumbnailData screenshotTask(int taskId) {
+ @Override public TaskSnapshot screenshotTask(int taskId) {
try {
- final TaskSnapshot snapshot =
- ActivityTaskManager.getService().takeTaskSnapshot(taskId);
- if (snapshot != null) {
- return new ThumbnailData(snapshot);
- }
+ return ActivityTaskManager.getService().takeTaskSnapshot(taskId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to screenshot task", e);
}
@@ -351,30 +350,24 @@
}
@Override public void setInputConsumerEnabled(boolean enabled) {
- if (enabled) {
- // transient launches don't receive focus automatically. Since we are taking over
- // the gesture now, take focus explicitly.
- // This also moves recents back to top if the user gestured before a switch
- // animation finished.
- try {
- ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to set focused task", e);
- }
+ if (!enabled) return;
+ // transient launches don't receive focus automatically. Since we are taking over
+ // the gesture now, take focus explicitly.
+ // This also moves recents back to top if the user gestured before a switch
+ // animation finished.
+ try {
+ ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set focused task", e);
}
- if (mWrapped != null) mWrapped.setInputConsumerEnabled(enabled);
}
@Override public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
- if (mWrapped != null) mWrapped.setAnimationTargetsBehindSystemBars(behindSystemBars);
}
@Override public void setFinishTaskTransaction(int taskId,
PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
mPipTransaction = finishTransaction;
- if (mWrapped != null) {
- mWrapped.setFinishTaskTransaction(taskId, finishTransaction, overlay);
- }
}
@Override
@@ -384,7 +377,6 @@
Log.e(TAG, "Duplicate call to finish", new RuntimeException());
return;
}
- if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -457,7 +449,6 @@
// for releasing the leashes created by local.
mInfo.releaseAllSurfaces();
// Reset all members.
- mWrapped = null;
mListener = null;
mFinishCB = null;
mPausingTasks = null;
@@ -471,23 +462,20 @@
}
@Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
- if (mWrapped != null) mWrapped.setDeferCancelUntilNextTransition(defer, screenshot);
}
@Override public void cleanupScreenshot() {
- if (mWrapped != null) mWrapped.cleanupScreenshot();
}
@Override public void setWillFinishToHome(boolean willFinishToHome) {
mWillFinishToHome = willFinishToHome;
- if (mWrapped != null) mWrapped.setWillFinishToHome(willFinishToHome);
}
/**
* @see IRecentsAnimationController#removeTask
*/
@Override public boolean removeTask(int taskId) {
- return mWrapped != null ? mWrapped.removeTask(taskId) : false;
+ return false;
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index e0cf7b6..d8085b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -132,6 +132,7 @@
/**
* UiEvents that are logged to identify why face auth is being triggered.
+ *
* @param extraInfo is logged as the position. See [UiEventLogger#logWithInstanceIdAndPosition]
*/
enum class FaceAuthUiEvent
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index c1fae9e..33bea02 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -69,6 +69,7 @@
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
+ private DisappearAnimationListener mDisappearAnimationListener;
public KeyguardPasswordView(Context context) {
this(context, null);
@@ -186,9 +187,13 @@
return;
}
Insets shownInsets = controller.getShownStateInsets();
- Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0,
- (int) (-shownInsets.bottom / 4
- * anim.getAnimatedFraction())));
+ int dist = (int) (-shownInsets.bottom / 4
+ * anim.getAnimatedFraction());
+ Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0, dist));
+ if (mDisappearAnimationListener != null) {
+ mDisappearAnimationListener.setTranslationY(-dist);
+ }
+
controller.setInsetsAndAlpha(insets,
(float) animation.getAnimatedValue(),
anim.getAnimatedFraction());
@@ -209,6 +214,7 @@
controller.finish(false);
runOnFinishImeAnimationRunnable();
finishRunnable.run();
+ mDisappearAnimationListener = null;
Trace.endSection();
});
}
@@ -286,4 +292,19 @@
}
});
}
+
+ /**
+ * Listens to the progress of the disappear animation and handles it.
+ */
+ interface DisappearAnimationListener {
+ void setTranslationY(int transY);
+ }
+
+ /**
+ * Set an instance of the disappear animation listener to this class. This will be
+ * removed when the animation completes.
+ */
+ public void setDisappearAnimationListener(DisappearAnimationListener listener) {
+ mDisappearAnimationListener = listener;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index d221e22..a010c9a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -26,6 +26,7 @@
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowInsets;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -156,6 +157,15 @@
// TODO: Remove this workaround by ensuring such a race condition never happens.
mMainExecutor.executeDelayed(
this::updateSwitchImeButton, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
+ mView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+ @Override
+ public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+ if (!mKeyguardViewController.isBouncerShowing()) {
+ mView.hideKeyboard();
+ }
+ return insets;
+ }
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index f164e7d..2949616 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -174,6 +174,17 @@
private @Mode int mCurrentMode = MODE_UNINITIALIZED;
private int mWidth = -1;
+ /**
+ * This callback is used to animate KeyguardSecurityContainer and its child views based on
+ * the interaction with the ime. After
+ * {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)},
+ * {@link #onApplyWindowInsets} is called where we
+ * set the bottom padding to be the height of the keyboard. We use this padding to determine
+ * the delta of vertical distance for y-translation animations.
+ * Note that bottom padding is not set when the disappear animation is started because
+ * we are deferring the y translation logic to the animator in
+ * {@link KeyguardPasswordView#startDisappearAnimation(Runnable)}
+ */
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -214,7 +225,6 @@
continue;
}
interpolatedFraction = animation.getInterpolatedFraction();
-
final int paddingBottom = (int) MathUtils.lerp(
start, end,
interpolatedFraction);
@@ -569,13 +579,21 @@
*/
public void startDisappearAnimation(SecurityMode securitySelection) {
mDisappearAnimRunning = true;
- mViewMode.startDisappearAnimation(securitySelection);
+ if (securitySelection == SecurityMode.Password
+ && mSecurityViewFlipper.getSecurityView() instanceof KeyguardPasswordView) {
+ ((KeyguardPasswordView) mSecurityViewFlipper.getSecurityView())
+ .setDisappearAnimationListener(this::setTranslationY);
+ } else {
+ mViewMode.startDisappearAnimation(securitySelection);
+ }
}
/**
* This will run when the bouncer shows in all cases except when the user drags the bouncer up.
*/
public void startAppearAnimation(SecurityMode securityMode) {
+ setTranslationY(0f);
+ setAlpha(1f);
updateChildren(0 /* translationY */, 1f /* alpha */);
mViewMode.startAppearAnimation(securityMode);
}
@@ -624,7 +642,13 @@
int inset = max(bottomInset, imeInset);
int paddingBottom = max(inset, getContext().getResources()
.getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin));
- setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+ // If security mode is password, we rely on the animation value of defined in
+ // KeyguardPasswordView to determine the y translation animation.
+ // This means that we will prevent the WindowInsetsAnimationCallback from setting any y
+ // translation values by preventing the setting of the padding here.
+ if (!mDisappearAnimRunning) {
+ setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+ }
return insets.inset(0, 0, 0, inset);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1402de0..866b502 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -74,11 +74,9 @@
import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.annotation.SuppressLint;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AlarmManager;
-import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
@@ -109,7 +107,6 @@
import android.nfc.NfcAdapter;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -182,6 +179,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@@ -2225,7 +2223,7 @@
handleDevicePolicyManagerStateChanged(msg.arg1);
break;
case MSG_USER_SWITCHING:
- handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
+ handleUserSwitching(msg.arg1, (CountDownLatch) msg.obj);
break;
case MSG_USER_SWITCH_COMPLETE:
handleUserSwitchComplete(msg.arg1);
@@ -2351,11 +2349,7 @@
mHandler, UserHandle.ALL);
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ mUserTracker.addCallback(mUserChangedCallback, mainExecutor);
mTrustManager.registerTrustListener(this);
@@ -2497,17 +2491,17 @@
return mIsFaceEnrolled;
}
- private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
+ private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
@Override
- public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+ public void onUserChanging(int newUser, Context userContext, CountDownLatch latch) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
- newUserId, 0, reply));
+ newUser, 0, latch));
}
@Override
- public void onUserSwitchComplete(int newUserId) {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
- newUserId, 0));
+ newUser, 0));
}
};
@@ -3237,7 +3231,7 @@
* Handle {@link #MSG_USER_SWITCHING}
*/
@VisibleForTesting
- void handleUserSwitching(int userId, IRemoteCallback reply) {
+ void handleUserSwitching(int userId, CountDownLatch latch) {
Assert.isMainThread();
clearBiometricRecognized();
boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
@@ -3250,11 +3244,7 @@
cb.onUserSwitching(userId);
}
}
- try {
- reply.sendResult(null);
- } catch (RemoteException e) {
- mLogger.logException(e, "Ignored exception while userSwitching");
- }
+ latch.countDown();
}
/**
@@ -4027,13 +4017,7 @@
mContext.getContentResolver().unregisterContentObserver(mTimeFormatChangeObserver);
}
- try {
- ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver);
- } catch (RemoteException e) {
- mLogger.logException(
- e,
- "RemoteException onDestroy. cannot unregister userSwitchObserver");
- }
+ mUserTracker.removeCallback(mUserChangedCallback);
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index b30a0e0..ad66909 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -51,7 +51,6 @@
private float mStartRadius;
private float mEndRadius;
private int mHeight;
- private boolean mInitialized;
private static final int EXPAND_ANIMATION_MS = 100;
private static final int EXPAND_COLOR_ANIMATION_MS = 50;
@@ -93,15 +92,15 @@
}
void onLayout(int height) {
+ boolean shouldUpdateHeight = height != mHeight;
mHeight = height;
mStartRadius = height / 2f;
mEndRadius = height / 4f;
mExpandAnimator.setFloatValues(mStartRadius, mEndRadius);
mContractAnimator.setFloatValues(mEndRadius, mStartRadius);
// Set initial corner radius.
- if (!mInitialized) {
+ if (shouldUpdateHeight) {
mBackground.setCornerRadius(mStartRadius);
- mInitialized = true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index ce42534..0002ae9 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -38,7 +38,6 @@
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -347,10 +346,9 @@
}
if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
updatePercentText();
- addView(mBatteryPercentView,
- new ViewGroup.LayoutParams(
- LayoutParams.WRAP_CONTENT,
- LayoutParams.MATCH_PARENT));
+ addView(mBatteryPercentView, new LayoutParams(
+ LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
}
} else {
if (showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 709ddf5..52312b8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -97,7 +97,6 @@
val iconContentDescription = getIconContentDescription(newState)
if (iconContentDescription != null) {
iconView.contentDescription = iconContentDescription
- iconViewOverlay.contentDescription = iconContentDescription
}
iconView.frame = 0
@@ -152,7 +151,7 @@
STATE_AUTHENTICATING_ANIMATING_IN,
STATE_AUTHENTICATING,
STATE_PENDING_CONFIRMATION,
- STATE_AUTHENTICATED -> R.string.accessibility_fingerprint_dialog_fingerprint_icon
+ STATE_AUTHENTICATED -> R.string.security_settings_sfps_enroll_find_sensor_message
STATE_ERROR,
STATE_HELP -> R.string.biometric_dialog_try_again
else -> null
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
index fabc1c1..e16121d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
@@ -49,8 +49,8 @@
/**
* @property messagesToDefer messages that shouldn't show immediately when received, but may be
- * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
- * percentage of all passed acquired frames.
+ * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
+ * percentage of all passed acquired frames.
*/
open class BiometricMessageDeferral(
private val messagesToDefer: Set<Int>,
@@ -127,8 +127,9 @@
/**
* Get the most frequent deferred message that meets the [threshold] percentage of processed
* frames.
+ *
* @return null if no acquiredInfo have been deferred OR deferred messages didn't meet the
- * [threshold] percentage.
+ * [threshold] percentage.
*/
fun getDeferredMessage(): CharSequence? {
mostFrequentAcquiredInfoToDefer?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index ac6a22c..f7d87fc 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -492,7 +492,9 @@
displayManager,
handler,
BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
- ) { onOrientationChanged(reason) }
+ ) {
+ onOrientationChanged(reason)
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 2d0d52e..231e7a4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -348,6 +348,7 @@
/**
* Overrides non-bouncer show logic in shouldPauseAuth to still show icon.
+ *
* @return whether the udfpsBouncer has been newly shown or hidden
*/
private fun showUdfpsBouncer(show: Boolean): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
index 28bc2b7..6854b50 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
@@ -76,5 +76,6 @@
| time: $time
| gestureStart: $gestureStart
|}
- """.trimMargin()
+ """
+ .trimMargin()
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
index a0b19dc..c0e1717 100644
--- a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
@@ -26,7 +26,6 @@
/**
* Convenience wrapper around [SendChannel.trySend] that also logs on failure. This is the
* equivalent of calling:
- *
* ```
* sendChannel.trySend(element).onFailure {
* Log.e(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
index b3c18fb..3744344 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
@@ -86,6 +86,7 @@
*
* When the favorites for that application are returned, they will be removed from the auxiliary
* file immediately, so they won't be retrieved again.
+ *
* @param componentName the name of the service that provided the controls
* @return a list of structures with favorites
*/
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 822190f..3555d0a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -166,6 +166,19 @@
)
/**
+ * Removes favorites for a given component
+ * @param componentName the name of the service that provides the [Control]
+ * @return true when favorites is scheduled for deletion
+ */
+ fun removeFavorites(componentName: ComponentName): Boolean
+
+ /**
+ * Checks if the favorites can be removed. You can't remove components from the preferred list.
+ * @param componentName the name of the service that provides the [Control]
+ */
+ fun canRemoveFavorites(componentName: ComponentName): Boolean
+
+ /**
* Replaces the favorites for the given structure.
*
* Calling this method will eliminate the previous selection of favorites and replace it with a
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 700f4f6..a171f43 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -499,6 +499,21 @@
}
}
+ override fun canRemoveFavorites(componentName: ComponentName): Boolean =
+ !authorizedPanelsRepository.getPreferredPackages().contains(componentName.packageName)
+
+ override fun removeFavorites(componentName: ComponentName): Boolean {
+ if (!confirmAvailability()) return false
+ if (!canRemoveFavorites(componentName)) return false
+
+ executor.execute {
+ Favorites.removeStructures(componentName)
+ authorizedPanelsRepository.removeAuthorizedPanels(setOf(componentName.packageName))
+ persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+ }
+ return true
+ }
+
override fun replaceFavoritesForStructure(structureInfo: StructureInfo) {
if (!confirmAvailability()) return
executor.execute {
@@ -657,10 +672,11 @@
return true
}
- fun removeStructures(componentName: ComponentName) {
+ fun removeStructures(componentName: ComponentName): Boolean {
val newFavMap = favMap.toMutableMap()
- newFavMap.remove(componentName)
+ val removed = newFavMap.remove(componentName) != null
favMap = newFavMap
+ return removed
}
fun addFavorite(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 72c3a94..217f4d8 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -84,7 +84,7 @@
private val BIND_FLAGS_PANEL = Context.BIND_AUTO_CREATE or Context.BIND_NOT_PERCEPTIBLE
}
- private val intent = Intent().apply {
+ private val intent = Intent(ControlsProviderService.SERVICE_CONTROLS).apply {
component = componentName
putExtra(CALLBACK_BUNDLE, Bundle().apply {
putBinder(CALLBACK_TOKEN, token)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
index 3e672f3..ae9c37a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
@@ -26,6 +26,14 @@
/** A set of package names that the user has previously authorized to show panels. */
fun getAuthorizedPanels(): Set<String>
+ /** Preferred applications to query controls suggestions from */
+ fun getPreferredPackages(): Set<String>
+
/** Adds [packageNames] to the set of packages that the user has authorized to show panels. */
fun addAuthorizedPanels(packageNames: Set<String>)
+
+ /**
+ * Removes [packageNames] from the set of packages that the user has authorized to show panels.
+ */
+ fun removeAuthorizedPanels(packageNames: Set<String>)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
index f7e43a7..e51e832 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
@@ -37,10 +37,20 @@
return getAuthorizedPanelsInternal(instantiateSharedPrefs())
}
+ override fun getPreferredPackages(): Set<String> =
+ context.resources.getStringArray(R.array.config_controlsPreferredPackages).toSet()
+
override fun addAuthorizedPanels(packageNames: Set<String>) {
addAuthorizedPanelsInternal(instantiateSharedPrefs(), packageNames)
}
+ override fun removeAuthorizedPanels(packageNames: Set<String>) {
+ with(instantiateSharedPrefs()) {
+ val currentSet = getAuthorizedPanelsInternal(this)
+ edit().putStringSet(KEY, currentSet - packageNames).apply()
+ }
+ }
+
private fun getAuthorizedPanelsInternal(sharedPreferences: SharedPreferences): Set<String> {
return sharedPreferences.getStringSet(KEY, emptySet())!!
}
@@ -63,15 +73,7 @@
// If we've never run this (i.e., the key doesn't exist), add the default packages
if (sharedPref.getStringSet(KEY, null) == null) {
- sharedPref
- .edit()
- .putStringSet(
- KEY,
- context.resources
- .getStringArray(R.array.config_controlsPreferredPackages)
- .toSet()
- )
- .apply()
+ sharedPref.edit().putStringSet(KEY, getPreferredPackages()).apply()
}
return sharedPref
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
index bb2e2d7..06d4a08 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
@@ -38,7 +38,6 @@
/**
* Manager to display a dialog to prompt user to enable controls related Settings:
- *
* * [Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]
* * [Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS]
*/
@@ -46,20 +45,19 @@
/**
* Shows the corresponding dialog. In order for a dialog to appear, the following must be true
- *
* * At least one of the Settings in [ControlsSettingsRepository] are `false`.
* * The dialog has not been seen by the user too many times (as defined by
- * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
+ * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
*
* When the dialogs are shown, the following outcomes are possible:
* * User cancels the dialog by clicking outside or going back: we register that the dialog was
- * seen but the settings don't change.
+ * seen but the settings don't change.
* * User responds negatively to the dialog: we register that the user doesn't want to change
- * the settings (dialog will not appear again) and the settings don't change.
+ * the settings (dialog will not appear again) and the settings don't change.
* * User responds positively to the dialog: the settings are set to `true` and the dialog will
- * not appear again.
+ * not appear again.
* * SystemUI closes the dialogs (for example, the activity showing it is closed). In this case,
- * we don't modify anything.
+ * we don't modify anything.
*
* Of those four scenarios, only the first three will cause [onAttemptCompleted] to be called.
* It will also be called if the dialogs are not shown.
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index 3a3f9b4..bf0a692 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -68,7 +68,7 @@
getLifecycle().addObserver(
ControlsAnimations.observerForAnimations(
- requireViewById<ViewGroup>(R.id.control_detail_root),
+ requireViewById(R.id.control_detail_root),
window,
intent,
!featureFlags.isEnabled(Flags.USE_APP_PANELS)
@@ -95,7 +95,7 @@
override fun onStart() {
super.onStart()
- parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
+ parent = requireViewById(R.id.control_detail_root)
parent.alpha = 0f
if (featureFlags.isEnabled(Flags.USE_APP_PANELS) && !keyguardStateController.isUnlocked) {
controlsSettingsDialogManager.maybeShowDialog(this) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
new file mode 100644
index 0000000..d6cfb79
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 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.controls.ui
+
+import android.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import java.util.function.Consumer
+import javax.inject.Inject
+
+class ControlsDialogsFactory(private val internalDialogFactory: (Context) -> SystemUIDialog) {
+
+ @Inject constructor() : this({ SystemUIDialog(it) })
+
+ fun createRemoveAppDialog(
+ context: Context,
+ appName: CharSequence,
+ response: Consumer<Boolean>
+ ): Dialog {
+ val listener =
+ DialogInterface.OnClickListener { _, which ->
+ response.accept(which == DialogInterface.BUTTON_POSITIVE)
+ }
+ return internalDialogFactory(context).apply {
+ setTitle(context.getString(R.string.controls_panel_remove_app_authorization, appName))
+ setCanceledOnTouchOutside(true)
+ setOnCancelListener { response.accept(false) }
+ setPositiveButton(R.string.controls_dialog_remove, listener)
+ setNeutralButton(R.string.cancel, listener)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 9405c60..c61dad6 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -21,6 +21,7 @@
import android.animation.ObjectAnimator
import android.app.Activity
import android.app.ActivityOptions
+import android.app.Dialog
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
@@ -52,7 +53,6 @@
import com.android.systemui.R
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsServiceInfo
-import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
@@ -64,6 +64,7 @@
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -83,7 +84,7 @@
import dagger.Lazy
import java.io.PrintWriter
import java.text.Collator
-import java.util.Optional
+import java.util.*
import java.util.function.Consumer
import javax.inject.Inject
@@ -108,6 +109,7 @@
private val controlsSettingsRepository: ControlsSettingsRepository,
private val authorizedPanelsRepository: AuthorizedPanelsRepository,
private val featureFlags: FeatureFlags,
+ private val dialogsFactory: ControlsDialogsFactory,
dumpManager: DumpManager
) : ControlsUiController, Dumpable {
@@ -122,6 +124,7 @@
private const val ADD_CONTROLS_ID = 1L
private const val ADD_APP_ID = 2L
private const val EDIT_CONTROLS_ID = 3L
+ private const val REMOVE_APP_ID = 4L
}
private var selectedItem: SelectedItem = SelectedItem.EMPTY_SELECTION
@@ -151,6 +154,7 @@
private var openAppIntent: Intent? = null
private var overflowMenuAdapter: BaseAdapter? = null
+ private var removeAppDialog: Dialog? = null
private val onSeedingComplete = Consumer<Boolean> {
accepted ->
@@ -330,6 +334,31 @@
}
}
+ @VisibleForTesting
+ internal fun startRemovingApp(componentName: ComponentName, appName: CharSequence) {
+ removeAppDialog?.cancel()
+ removeAppDialog = dialogsFactory.createRemoveAppDialog(context, appName) {
+ if (!controlsController.get().removeFavorites(componentName)) {
+ return@createRemoveAppDialog
+ }
+ if (
+ sharedPreferences.getString(PREF_COMPONENT, "") ==
+ componentName.flattenToString()
+ ) {
+ sharedPreferences
+ .edit()
+ .remove(PREF_COMPONENT)
+ .remove(PREF_STRUCTURE_OR_APP_NAME)
+ .remove(PREF_IS_PANEL)
+ .commit()
+ }
+
+ allStructures = controlsController.get().getFavorites()
+ selectedItem = getPreferredSelectedItem(allStructures)
+ reload(parent)
+ }.apply { show() }
+ }
+
private fun startTargetedActivity(si: StructureInfo, klazz: Class<*>) {
val i = Intent(activityContext, klazz)
putIntentExtras(i, si)
@@ -433,7 +462,10 @@
val currentApps = panelsAndStructures.map { it.componentName }.toSet()
val allApps = controlsListingController.get()
.getCurrentServices().map { it.componentName }.toSet()
- createMenu(extraApps = (allApps - currentApps).isNotEmpty())
+ createMenu(
+ selectionItem = selectionItem,
+ extraApps = (allApps - currentApps).isNotEmpty(),
+ )
}
private fun createPanelView(componentName: ComponentName) {
@@ -472,7 +504,7 @@
}
}
- private fun createMenu(extraApps: Boolean) {
+ private fun createMenu(selectionItem: SelectionItem, extraApps: Boolean) {
val isPanel = selectedItem is SelectedItem.PanelItem
val selectedStructure = (selectedItem as? SelectedItem.StructureItem)?.structure
?: EMPTY_STRUCTURE
@@ -490,6 +522,13 @@
ADD_APP_ID
))
}
+ if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED) &&
+ controlsController.get().canRemoveFavorites(selectedItem.componentName)) {
+ add(OverflowMenuAdapter.MenuItem(
+ context.getText(R.string.controls_menu_remove),
+ REMOVE_APP_ID,
+ ))
+ }
} else {
add(OverflowMenuAdapter.MenuItem(
context.getText(R.string.controls_menu_add),
@@ -529,6 +568,9 @@
ADD_APP_ID -> startProviderSelectorActivity()
ADD_CONTROLS_ID -> startFavoritingActivity(selectedStructure)
EDIT_CONTROLS_ID -> startEditingActivity(selectedStructure)
+ REMOVE_APP_ID -> startRemovingApp(
+ selectedStructure.componentName, selectionItem.appName
+ )
}
dismiss()
}
@@ -546,8 +588,12 @@
RenderInfo.registerComponentIcon(it.componentName, it.icon)
}
- var adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
- addAll(items)
+ val adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
+ add(selected)
+ addAll(items
+ .filter { it !== selected }
+ .sortedBy { it.appName.toString() }
+ )
}
val iconSize = context.resources
@@ -728,6 +774,7 @@
it.value.dismiss()
}
controlActionCoordinator.closeDialogs()
+ removeAppDialog?.cancel()
}
override fun hide(parent: ViewGroup) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
index 3b6ab20..78e87ca 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
@@ -71,7 +71,7 @@
taskView.post {
val roundedCorner =
activityContext.resources.getDimensionPixelSize(
- R.dimen.notification_corner_radius
+ R.dimen.controls_panel_corner_radius
)
val radii = FloatArray(8) { roundedCorner.toFloat() }
taskView.background =
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index c96946b..7a1abf4 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -75,6 +75,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.connectivity.ConnectivityModule;
+import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
@@ -257,9 +258,7 @@
abstract FingerprintInteractiveToAuthProvider optionalFingerprintInteractiveToAuthProvider();
@BindsOptionalOf
- //TODO(b/269430792 remove full qualifier. Full qualifier is used to avoid merge conflict.)
- abstract com.android.systemui.statusbar.events.SystemStatusAnimationScheduler
- optionalSystemStatusAnimationScheduler();
+ abstract SystemStatusAnimationScheduler optionalSystemStatusAnimationScheduler();
@SysUISingleton
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index 84f83f1..45ff963 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -128,7 +128,6 @@
*
* This is equivalent of creating a listener manually and adding an event handler for the given
* command, like so:
- *
* ```
* class Demoable {
* private val demoHandler = object : DemoMode {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c3bd5d9..ca1cef3 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -184,6 +184,7 @@
/**
* Ends the dream content and dream overlay animations, if they're currently running.
+ *
* @see [AnimatorSet.end]
*/
fun endAnimations() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index f282aae..9374ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -16,6 +16,8 @@
package com.android.systemui.dreams;
+import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
+
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
@@ -76,6 +78,7 @@
private final ComponentName mLowLightDreamComponent;
private final UiEventLogger mUiEventLogger;
private final WindowManager mWindowManager;
+ private final String mWindowTitle;
// A reference to the {@link Window} used to hold the dream overlay.
private Window mWindow;
@@ -151,7 +154,8 @@
TouchInsetManager touchInsetManager,
@Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
ComponentName lowLightDreamComponent,
- DreamOverlayCallbackController dreamOverlayCallbackController) {
+ DreamOverlayCallbackController dreamOverlayCallbackController,
+ @Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) {
mContext = context;
mExecutor = executor;
mWindowManager = windowManager;
@@ -161,6 +165,7 @@
mStateController = stateController;
mUiEventLogger = uiEventLogger;
mDreamOverlayCallbackController = dreamOverlayCallbackController;
+ mWindowTitle = windowTitle;
final ViewModelStore viewModelStore = new ViewModelStore();
final Complication.Host host =
@@ -277,7 +282,7 @@
private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
mWindow = new PhoneWindow(mContext);
// Default to SystemUI name for TalkBack.
- mWindow.setTitle("");
+ mWindow.setTitle(mWindowTitle);
mWindow.setAttributes(layoutParams);
mWindow.setWindowManager(null, layoutParams.token, "DreamOverlay", true);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index e39073b..ff1f312 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -28,6 +28,8 @@
import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -68,6 +70,7 @@
private final DreamSmartspaceController mSmartSpaceController;
private final DreamOverlayStateController mDreamOverlayStateController;
private final SmartSpaceComplication mComplication;
+ private final FeatureFlags mFeatureFlags;
private final BcSmartspaceDataPlugin.SmartspaceTargetListener mSmartspaceListener =
new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@@ -85,15 +88,21 @@
DreamOverlayStateController dreamOverlayStateController,
SmartSpaceComplication smartSpaceComplication,
DreamSmartspaceController smartSpaceController,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+ @Named(DREAM_PRETEXT_MONITOR) Monitor monitor,
+ FeatureFlags featureFlags) {
super(monitor);
mDreamOverlayStateController = dreamOverlayStateController;
mComplication = smartSpaceComplication;
mSmartSpaceController = smartSpaceController;
+ mFeatureFlags = featureFlags;
}
@Override
public void onStart() {
+ if (mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)) {
+ return;
+ }
+
mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
@Override
public void onStateChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index f598c36..f130026 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -23,6 +23,7 @@
import com.android.dream.lowlight.dagger.LowLightDreamModule;
import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
@@ -66,6 +67,8 @@
String DREAM_SUPPORTED = "dream_supported";
String DREAM_PRETEXT_CONDITIONS = "dream_pretext_conditions";
String DREAM_PRETEXT_MONITOR = "dream_prtext_monitor";
+ String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
+
/**
* Provides the dream component
@@ -139,4 +142,11 @@
@Named(DREAM_PRETEXT_CONDITIONS) Set<Condition> pretextConditions) {
return new Monitor(executor, pretextConditions);
}
+
+ /** */
+ @Provides
+ @Named(DREAM_OVERLAY_WINDOW_TITLE)
+ static String providesDreamOverlayWindowTitle(@Main Resources resources) {
+ return resources.getString(R.string.app_label);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 92bfc53..9264e6c 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -151,12 +151,6 @@
val CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES =
releasedFlag(216, "customizable_lock_screen_quick_affordances")
- /** Shows chipbar UI whenever the device is unlocked by ActiveUnlock (watch). */
- // TODO(b/256513609): Tracking Bug
- @JvmField
- val ACTIVE_UNLOCK_CHIPBAR =
- resourceBooleanFlag(217, R.bool.flag_active_unlock_chipbar, "active_unlock_chipbar")
-
/**
* Migrates control of the LightRevealScrim's reveal effect and amount from legacy code to the
* new KeyguardTransitionRepository.
@@ -224,6 +218,10 @@
val SMARTSPACE_DATE_WEATHER_DECOUPLED =
sysPropBooleanFlag(403, "persist.sysui.ss.dw_decoupled", default = true)
+ // TODO(b/270223352): Tracking Bug
+ @JvmField
+ val HIDE_SMARTSPACE_ON_DREAM_OVERLAY = unreleasedFlag(404, "hide_smartspace_on_dream_overlay")
+
// 500 - quick settings
val PEOPLE_TILE = resourceBooleanFlag(502, R.bool.flag_conversations, "people_tile")
@@ -259,8 +257,7 @@
/** Enables new QS Edit Mode visual refresh */
// TODO(b/269787742): Tracking Bug
@JvmField
- val ENABLE_NEW_QS_EDIT_MODE =
- unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false)
+ val ENABLE_NEW_QS_EDIT_MODE = unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false)
// 600- status bar
@@ -363,12 +360,18 @@
// TODO(b/267166152) : Tracking Bug
val MEDIA_RETAIN_RECOMMENDATIONS = releasedFlag(916, "media_retain_recommendations")
+ // TODO(b/270437894): Tracking Bug
+ val MEDIA_REMOTE_RESUME = unreleasedFlag(917, "media_remote_resume")
+
// 1000 - dock
val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
// TODO(b/254512758): Tracking Bug
@JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
+ // TODO(b/270882464): Tracking Bug
+ val ENABLE_DOCK_SETUP_V2 = unreleasedFlag(1005, "enable_dock_setup_v2")
+
// TODO(b/265045965): Tracking Bug
val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
@@ -614,11 +617,6 @@
@JvmField
val OUTPUT_SWITCHER_DEVICE_STATUS = releasedFlag(2502, "output_switcher_device_status")
- // TODO(b/20911786): Tracking Bug
- @JvmField
- val OUTPUT_SWITCHER_SHOW_API_ENABLED =
- releasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true)
-
// 2700 - unfold transitions
// TODO(b/265764985): Tracking Bug
@Keep
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 949bcfb..e43f83b 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -2056,6 +2056,10 @@
|| Intent.ACTION_SCREEN_OFF.equals(action)) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (!SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) {
+ // These broadcasts are usually received when locking the device, swiping up to
+ // home (which collapses the shade), etc. In those cases, we usually don't want
+ // to animate this dialog back into the view, so we disable the exit animations.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISMISS, reason));
}
} else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
index 70faf40..dd5c5d3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
@@ -18,15 +18,19 @@
package com.android.systemui.keyboard.data.repository
import android.hardware.input.InputManager
+import android.hardware.input.InputManager.KeyboardBacklightListener
+import android.hardware.input.KeyboardBacklightState
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyboard.data.model.BacklightModel
+import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -51,24 +55,22 @@
private val connectedDeviceIds: Flow<Set<Int>> =
conflatedCallbackFlow {
- fun send(element: Set<Int>) = trySendWithFailureLogging(element, TAG)
-
var connectedKeyboards = inputManager.inputDeviceIds.toSet()
val listener =
object : InputManager.InputDeviceListener {
override fun onInputDeviceAdded(deviceId: Int) {
connectedKeyboards = connectedKeyboards + deviceId
- send(connectedKeyboards)
+ sendWithLogging(connectedKeyboards)
}
override fun onInputDeviceChanged(deviceId: Int) = Unit
override fun onInputDeviceRemoved(deviceId: Int) {
connectedKeyboards = connectedKeyboards - deviceId
- send(connectedKeyboards)
+ sendWithLogging(connectedKeyboards)
}
}
- send(connectedKeyboards)
+ sendWithLogging(connectedKeyboards)
inputManager.registerInputDeviceListener(listener, /* handler= */ null)
awaitClose { inputManager.unregisterInputDeviceListener(listener) }
}
@@ -78,6 +80,16 @@
replay = 1,
)
+ private val backlightStateListener: Flow<KeyboardBacklightState> = conflatedCallbackFlow {
+ val listener = KeyboardBacklightListener { _, state, isTriggeredByKeyPress ->
+ if (isTriggeredByKeyPress) {
+ sendWithLogging(state)
+ }
+ }
+ inputManager.registerKeyboardBacklightListener(Executor(Runnable::run), listener)
+ awaitClose { inputManager.unregisterKeyboardBacklightListener(listener) }
+ }
+
override val keyboardConnected: Flow<Boolean> =
connectedDeviceIds
.map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } }
@@ -85,9 +97,13 @@
.flowOn(backgroundDispatcher)
override val backlight: Flow<BacklightModel> =
- conflatedCallbackFlow {
- // TODO(b/268645734) register BacklightListener
- }
+ backlightStateListener
+ .map { BacklightModel(it.brightnessLevel, it.maxBrightnessLevel) }
+ .flowOn(backgroundDispatcher)
+
+ private fun <T> SendChannel<T>.sendWithLogging(element: T) {
+ trySendWithFailureLogging(element, TAG)
+ }
private fun isPhysicalFullKeyboard(deviceId: Int): Boolean {
val device = inputManager.getInputDevice(deviceId)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index be73f85..ef0c9a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -134,7 +134,9 @@
.flowOn(backgroundDispatcher)
.distinctUntilChanged()
.onEach { settingsValue = it }
- ) { callbackFlowValue, _ -> callbackFlowValue }
+ ) { callbackFlowValue, _ ->
+ callbackFlowValue
+ }
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
return if (controller.isZenAvailable) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
index 0066785..356a8fb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
@@ -102,7 +102,8 @@
// setup).
emit(Unit)
}
- ) { _, _ -> }
+ ) { _, _ ->
+ }
.flatMapLatest {
conflatedCallbackFlow {
// We want to instantiate a new SharedPreferences instance each time either the
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
index baadc66..84abf57 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -24,8 +24,10 @@
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
import android.os.Looper
import android.os.UserHandle
+import android.util.Log
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.Dumpable
+import com.android.systemui.R
import com.android.systemui.biometrics.AuthController
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
@@ -35,6 +37,7 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.shared.model.DevicePosture
import com.android.systemui.user.data.repository.UserRepository
import java.io.PrintWriter
import javax.inject.Inject
@@ -47,8 +50,10 @@
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
@@ -82,6 +87,12 @@
/** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
+
+ /**
+ * Whether face authentication is supported for the current device posture. Face auth can be
+ * restricted to specific postures using [R.integer.config_face_auth_supported_posture]
+ */
+ val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
}
@SysUISingleton
@@ -98,11 +109,27 @@
@Background backgroundDispatcher: CoroutineDispatcher,
biometricManager: BiometricManager?,
@Main looper: Looper,
+ devicePostureRepository: DevicePostureRepository,
dumpManager: DumpManager,
) : BiometricSettingsRepository, Dumpable {
+ override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+
init {
dumpManager.registerDumpable(this)
+ val configFaceAuthSupportedPosture =
+ DevicePosture.toPosture(
+ context.resources.getInteger(R.integer.config_face_auth_supported_posture)
+ )
+ isFaceAuthSupportedInCurrentPosture =
+ if (configFaceAuthSupportedPosture == DevicePosture.UNKNOWN) {
+ flowOf(true)
+ } else {
+ devicePostureRepository.currentDevicePosture.map {
+ it == configFaceAuthSupportedPosture
+ }
+ }
+ .onEach { Log.d(TAG, "isFaceAuthSupportedInCurrentPosture value changed to: $it") }
}
override fun dump(pw: PrintWriter, args: Array<String?>) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
new file mode 100644
index 0000000..adb1e01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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.keyguard.data.repository
+
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+/** Provide current device posture state. */
+interface DevicePostureRepository {
+ /** Provides the current device posture. */
+ val currentDevicePosture: Flow<DevicePosture>
+}
+
+@SysUISingleton
+class DevicePostureRepositoryImpl
+@Inject
+constructor(private val postureController: DevicePostureController) : DevicePostureRepository {
+ override val currentDevicePosture: Flow<DevicePosture>
+ get() = conflatedCallbackFlow {
+ val sendPostureUpdate = { posture: Int ->
+ val currentDevicePosture = DevicePosture.toPosture(posture)
+ trySendWithFailureLogging(
+ currentDevicePosture,
+ TAG,
+ "Error sending posture update to $currentDevicePosture"
+ )
+ }
+ val callback = DevicePostureController.Callback { sendPostureUpdate(it) }
+ postureController.addCallback(callback)
+ sendPostureUpdate(postureController.devicePosture)
+
+ awaitClose { postureController.removeCallback(callback) }
+ }
+
+ companion object {
+ const val TAG = "PostureRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 0e85347..86e5cd7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -53,6 +53,7 @@
val primaryBouncerScrimmed: StateFlow<Boolean>
/**
* Set how much of the notification panel is showing on the screen.
+ *
* ```
* 0f = panel fully hidden = bouncer fully showing
* 1f = panel fully showing = bouncer fully hidden
@@ -134,6 +135,7 @@
override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
/**
* Set how much of the notification panel is showing on the screen.
+ *
* ```
* 0f = panel fully hidden = bouncer fully showing
* 1f = panel fully showing = bouncer fully hidden
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 4a262f5..f27f899 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -31,6 +31,8 @@
@Binds
fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
+ @Binds fun devicePostureRepository(impl: DevicePostureRepositoryImpl): DevicePostureRepository
+
@Binds
fun biometricSettingsRepository(
impl: BiometricSettingsRepositoryImpl
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index 0140529..eae40d6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -50,6 +50,7 @@
/**
* Sets the correct bouncer states to show the alternate bouncer if it can show.
+ *
* @return whether alternateBouncer is visible
*/
fun show(): Boolean {
@@ -74,6 +75,7 @@
* Sets the correct bouncer states to hide the bouncer. Should only be called through
* StatusBarKeyguardViewManager until ScrimController is refactored to use
* alternateBouncerInteractor.
+ *
* @return true if the alternate bouncer was newly hidden, else false.
*/
fun hide(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index 310f44d..e6568f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -71,8 +71,7 @@
isPrimaryBouncerShowing,
lastStartedTransitionStep,
wakefulnessState,
- isAodAvailable
- ) ->
+ isAodAvailable) ->
if (
!isAlternateBouncerShowing &&
!isPrimaryBouncerShowing &&
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index 9b5f7f6..bc3c720 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -120,7 +120,7 @@
* Notifies that a quick affordance has been "triggered" (clicked) by the user.
*
* @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of
- * the affordance that was clicked
+ * the affordance that was clicked
* @param expandable An optional [Expandable] for the activity- or dialog-launch animation
*/
fun onQuickAffordanceTriggered(
@@ -199,9 +199,9 @@
*
* @param slotId The ID of the slot.
* @param affordanceId The ID of the affordance to remove; if `null`, removes all affordances
- * from the slot.
+ * from the slot.
* @return `true` if the affordance was successfully removed; `false` otherwise (for example, if
- * the affordance was not on the slot to begin with).
+ * the affordance was not on the slot to begin with).
*/
suspend fun unselect(slotId: String, affordanceId: String?): Boolean {
check(isUsingRepository)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
new file mode 100644
index 0000000..fff7cfe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.keyguard.shared.model
+
+import com.android.systemui.statusbar.policy.DevicePostureController
+
+/** Represents the possible posture states of the device. */
+enum class DevicePosture {
+ UNKNOWN,
+ CLOSED,
+ HALF_OPENED,
+ OPENED,
+ FLIPPED;
+
+ companion object {
+ fun toPosture(@DevicePostureController.DevicePostureInt posture: Int): DevicePosture {
+ return when (posture) {
+ DevicePostureController.DEVICE_POSTURE_CLOSED -> CLOSED
+ DevicePostureController.DEVICE_POSTURE_HALF_OPENED -> HALF_OPENED
+ DevicePostureController.DEVICE_POSTURE_OPENED -> OPENED
+ DevicePostureController.DEVICE_POSTURE_FLIPPED -> FLIPPED
+ DevicePostureController.DEVICE_POSTURE_UNKNOWN -> UNKNOWN
+ else -> UNKNOWN
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index ab009f4..2a9060f6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -342,7 +342,13 @@
if (viewModel.isClickable) {
if (viewModel.useLongPress) {
view.setOnTouchListener(
- OnTouchListener(view, viewModel, messageDisplayer, vibratorHelper)
+ OnTouchListener(
+ view,
+ viewModel,
+ messageDisplayer,
+ vibratorHelper,
+ falsingManager,
+ )
)
} else {
view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager)))
@@ -371,6 +377,7 @@
private val viewModel: KeyguardQuickAffordanceViewModel,
private val messageDisplayer: (Int) -> Unit,
private val vibratorHelper: VibratorHelper?,
+ private val falsingManager: FalsingManager?,
) : View.OnTouchListener {
private val longPressDurationMs = ViewConfiguration.getLongPressTimeout().toLong()
@@ -395,7 +402,14 @@
.scaleY(PRESSED_SCALE)
.setDuration(longPressDurationMs)
.withEndAction {
- dispatchClick(viewModel.configKey)
+ if (
+ falsingManager
+ ?.isFalseLongTap(
+ FalsingManager.MODERATE_PENALTY
+ ) == false
+ ) {
+ dispatchClick(viewModel.configKey)
+ }
cancel()
}
}
@@ -421,7 +435,8 @@
// the pointer performs a click.
if (
viewModel.configKey != null &&
- distanceMoved(event) <= ViewConfiguration.getTouchSlop()
+ distanceMoved(event) <= ViewConfiguration.getTouchSlop() &&
+ falsingManager?.isFalseTap(FalsingManager.NO_PENALTY) == false
) {
dispatchClick(viewModel.configKey)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
index ef3f242..8671753 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
@@ -34,7 +34,7 @@
* @param viewModel The view-model that models the UI state.
* @param onSingleTap A callback to invoke when the system decides that there was a single tap.
* @param falsingManager [FalsingManager] for making sure the long-press didn't just happen in
- * the user's pocket.
+ * the user's pocket.
*/
@JvmStatic
fun bind(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
index 1e3b60c..ab9e6a4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
@@ -135,7 +135,7 @@
*
* @param initiallySelectedSlotId The ID of the initial slot to render as the selected one.
* @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be
- * highlighted (while all others are dimmed to make the selected one stand out).
+ * highlighted (while all others are dimmed to make the selected one stand out).
*/
fun enablePreviewMode(
initiallySelectedSlotId: String?,
@@ -187,6 +187,7 @@
previewMode.isInPreviewMode &&
previewMode.shouldHighlightSelectedAffordance &&
!isSelected,
+ forceInactive = previewMode.isInPreviewMode
)
}
.distinctUntilChanged()
@@ -198,6 +199,7 @@
isClickable: Boolean,
isSelected: Boolean,
isDimmed: Boolean,
+ forceInactive: Boolean,
): KeyguardQuickAffordanceViewModel {
return when (this) {
is KeyguardQuickAffordanceModel.Visible ->
@@ -213,7 +215,7 @@
)
},
isClickable = isClickable,
- isActivated = activationState is ActivationState.Active,
+ isActivated = !forceInactive && activationState is ActivationState.Active,
isSelected = isSelected,
useLongPress = quickAffordanceInteractor.useLongPress,
isDimmed = isDimmed,
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index d69ac7f..34a6740 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -47,13 +47,13 @@
* fresh one.
*
* @param coroutineContext An optional [CoroutineContext] to replace the dispatcher [block] is
- * invoked on.
+ * invoked on.
* @param block The block of code that should be run when the view becomes attached. It can end up
- * being invoked multiple times if the view is reattached after being detached.
+ * being invoked multiple times if the view is reattached after being detached.
* @return A [DisposableHandle] to invoke when the caller of the function destroys its [View] and is
- * no longer interested in the [block] being run the next time its attached. Calling this is an
- * optional optimization as the logic will be properly cleaned up and destroyed each time the view
- * is detached. Using this is not *thread-safe* and should only be used on the main thread.
+ * no longer interested in the [block] being run the next time its attached. Calling this is an
+ * optional optimization as the logic will be properly cleaned up and destroyed each time the view
+ * is detached. Using this is not *thread-safe* and should only be used on the main thread.
*/
@MainThread
fun View.repeatWhenAttached(
@@ -125,7 +125,6 @@
* The implementation requires the caller to call [onCreate] and [onDestroy] when the view is
* attached to or detached from a view hierarchy. After [onCreate] and before [onDestroy] is called,
* the implementation monitors window state in the following way
- *
* * If the window is not visible, we are in the [Lifecycle.State.CREATED] state
* * If the window is visible but not focused, we are in the [Lifecycle.State.STARTED] state
* * If the window is visible and focused, we are in the [Lifecycle.State.RESUMED] state
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index f7349a2..647e3a1 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -16,7 +16,6 @@
* Helper class for logging for [com.android.keyguard.faceauth.KeyguardFaceAuthManager]
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* adb shell settings put global systemui/buffer/KeyguardFaceAuthManagerLog <logLevel>
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
index 5acaa46..edc278d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -33,7 +33,6 @@
* Helper class for logging for [com.android.systemui.ScreenDecorations]
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* adb shell settings put global systemui/buffer/ScreenDecorationsLog <logLevel>
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 220993f..ca1ed1f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -62,6 +62,15 @@
return factory.create("NotifLog", maxSize, false /* systrace */);
}
+ /** Provides a logging buffer for all logs related to notifications on the lockscreen. */
+ @Provides
+ @SysUISingleton
+ @NotificationLockscreenLog
+ public static LogBuffer provideNotificationLockScreenLogBuffer(
+ LogBufferFactory factory) {
+ return factory.create("NotifLockscreenLog", 50, false /* systrace */);
+ }
+
/** Provides a logging buffer for logs related to heads up presentation of notifications. */
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
new file mode 100644
index 0000000..a2d381e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.plugins.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification & lockscreen related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationLockscreenLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 1712dab..29f273a 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -29,7 +29,6 @@
*
* Some parts of System UI maintain a lot of pieces of state at once.
* [com.android.systemui.plugins.log.LogBuffer] allows us to easily log change events:
- *
* - 10-10 10:10:10.456: state2 updated to newVal2
* - 10-10 10:11:00.000: stateN updated to StateN(val1=true, val2=1)
* - 10-10 10:11:02.123: stateN updated to StateN(val1=true, val2=2)
@@ -37,7 +36,6 @@
* - 10-10 10:11:06.000: stateN updated to StateN(val1=false, val2=3)
*
* However, it can sometimes be more useful to view the state changes in table format:
- *
* - timestamp--------- | state1- | state2- | ... | stateN.val1 | stateN.val2
* - -------------------------------------------------------------------------
* - 10-10 10:10:10.123 | val1--- | val2--- | ... | false------ | 0-----------
@@ -56,23 +54,18 @@
* individual fields.
*
* How it works:
- *
* 1) Create an instance of this buffer via [TableLogBufferFactory].
- *
* 2) For any states being logged, implement [Diffable]. Implementing [Diffable] allows the state to
- * only log the fields that have *changed* since the previous update, instead of always logging all
- * fields.
- *
+ * only log the fields that have *changed* since the previous update, instead of always logging
+ * all fields.
* 3) Each time a change in a state happens, call [logDiffs]. If your state is emitted using a
- * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs any
- * time your flow emits a new value.
+ * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs
+ * any time your flow emits a new value.
*
* When a dump occurs, there will be two dumps:
- *
* 1) The change events under the dumpable name "$name-changes".
- *
* 2) This class will coalesce all the diffs into a table format and log them under the dumpable
- * name "$name-table".
+ * name "$name-table".
*
* @param maxSize the maximum size of the buffer. Must be > 0.
*/
@@ -99,11 +92,10 @@
* The [newVal] object's method [Diffable.logDiffs] will be used to fetch the diffs.
*
* @param columnPrefix a prefix that will be applied to every column name that gets logged. This
- * ensures that all the columns related to the same state object will be grouped together in the
- * table.
- *
+ * ensures that all the columns related to the same state object will be grouped together in
+ * the table.
* @throws IllegalArgumentException if [columnPrefix] or column name contain "|". "|" is used as
- * the separator token for parsing, so it can't be present in any part of the column name.
+ * the separator token for parsing, so it can't be present in any part of the column name.
*/
@Synchronized
fun <T : Diffable<T>> logDiffs(columnPrefix: String, prevVal: T, newVal: T) {
@@ -117,7 +109,7 @@
* Logs change(s) to the buffer using [rowInitializer].
*
* @param rowInitializer a function that will be called immediately to store relevant data on
- * the row.
+ * the row.
*/
@Synchronized
fun logChange(columnPrefix: String, rowInitializer: (TableRowLogger) -> Unit) {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 7ccc43c..06668d3 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -38,7 +38,6 @@
*
* @param name a unique table name
* @param maxSize the buffer max size. See [adjustMaxSize]
- *
* @return a new [TableLogBuffer] registered with [DumpManager]
*/
fun create(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
index a057c9f..2509f21 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
@@ -187,6 +187,7 @@
/**
* Handle request to change the current position in the media track.
+ *
* @param position Place to seek to in the track.
*/
@AnyThread
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
index 0b57175..ae03f27 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
@@ -52,6 +52,7 @@
* Indicates if all the data is valid.
*
* TODO(b/230333302): Make MediaControlPanel more flexible so that we can display fewer than
+ *
* ```
* [NUM_REQUIRED_RECOMMENDATIONS].
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
index 97717a6..207df6b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
@@ -329,9 +329,8 @@
* Return the time since last active for the most-recent media.
*
* @param sortedEntries userEntries sorted from the earliest to the most-recent.
- *
* @return The duration in milliseconds from the most-recent media's last active timestamp to
- * the present. MAX_VALUE will be returned if there is no media.
+ * the present. MAX_VALUE will be returned if there is no media.
*/
private fun timeSinceActiveForMostRecentMedia(
sortedEntries: SortedMap<String, MediaData>
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index af60e0e..72c4aab 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -526,8 +526,8 @@
* through the internal listener pipeline.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait until
- * the next refresh-round before UI becomes visible. Should only be true if the update is
- * initiated by user's interaction.
+ * the next refresh-round before UI becomes visible. Should only be true if the update is
+ * initiated by user's interaction.
*/
private fun notifySmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
internalListeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
@@ -536,6 +536,7 @@
/**
* Called whenever the player has been paused or stopped for a while, or swiped from QQS. This
* will make the player not active anymore, hiding it from QQS and Keyguard.
+ *
* @see MediaData.active
*/
internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
@@ -1024,6 +1025,7 @@
* @param packageName Package name for the media app
* @param controller MediaController for the current session
* @return a Pair consisting of a list of media actions, and a list of ints representing which
+ *
* ```
* of those actions should be shown in the compact player
* ```
@@ -1127,6 +1129,7 @@
* [PlaybackState.ACTION_SKIP_TO_NEXT]
* @return
* ```
+ *
* A [MediaAction] with correct values set, or null if the state doesn't support it
*/
private fun getStandardAction(
@@ -1229,6 +1232,7 @@
}
/**
* Load a bitmap from a URI
+ *
* @param uri the uri to load
* @return bitmap, or null if couldn't be loaded
*/
@@ -1342,10 +1346,13 @@
fun onNotificationRemoved(key: String) {
Assert.isMainThread()
val removed = mediaEntries.remove(key) ?: return
-
+ val isEligibleForResume =
+ removed.isLocalSession() ||
+ (mediaFlags.isRemoteResumeAllowed() &&
+ removed.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) {
logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
- } else if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) {
+ } else if (useMediaResumption && removed.resumeAction != null && isEligibleForResume) {
convertToResumePlayer(key, removed)
} else if (mediaFlags.isRetainingPlayersEnabled()) {
handlePossibleRemoval(key, removed, notificationRemoved = true)
@@ -1519,15 +1526,13 @@
* notification key) or vice versa.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait
- * until the next refresh-round before UI becomes visible. True by default to take in place
- * immediately.
- *
+ * until the next refresh-round before UI becomes visible. True by default to take in
+ * place immediately.
* @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI
- * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
- * signal.
- *
+ * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
+ * signal.
* @param isSsReactivated indicates resume media card is reactivated by Smartspace
- * recommendation signal
+ * recommendation signal
*/
fun onMediaDataLoaded(
key: String,
@@ -1542,8 +1547,8 @@
* Called whenever there's new Smartspace media data loaded.
*
* @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true,
- * it will be prioritized as the first card. Otherwise, it will show up as the last card as
- * default.
+ * it will be prioritized as the first card. Otherwise, it will show up as the last card
+ * as default.
*/
fun onSmartspaceMediaDataLoaded(
key: String,
@@ -1558,8 +1563,8 @@
* Called whenever a previously existing Smartspace media data was removed.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait
- * until the next refresh-round before UI becomes visible. True by default to take in place
- * immediately.
+ * until the next refresh-round before UI becomes visible. True by default to take in
+ * place immediately.
*/
fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean = true) {}
}
@@ -1568,7 +1573,7 @@
* Converts the pass-in SmartspaceTarget to SmartspaceMediaData
*
* @return An empty SmartspaceMediaData with the valid target Id is returned if the
- * SmartspaceTarget's data is invalid.
+ * SmartspaceTarget's data is invalid.
*/
private fun toSmartspaceMediaData(target: SmartspaceTarget): SmartspaceMediaData {
var dismissIntent: Intent? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 6a512be..120704c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -408,9 +408,9 @@
* [LocalMediaManager.DeviceCallback.onAboutToConnectDeviceAdded] for more information.
*
* @property fullMediaDevice a full-fledged [MediaDevice] object representing the device. If
- * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
+ * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
* @property backupMediaDeviceData a backup [MediaDeviceData] object containing the minimum
- * information required to display the device. Only use if [fullMediaDevice] is null.
+ * information required to display the device. Only use if [fullMediaDevice] is null.
*/
private data class AboutToConnectDevice(
val fullMediaDevice: MediaDevice? = null,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
index 878962d..a1d9214 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
@@ -60,6 +60,7 @@
/**
* Callback representing that a media object is now expired:
+ *
* @param key Media control unique identifier
* @param timedOut True when expired for {@code PAUSED_MEDIA_TIMEOUT} for active media,
* ```
@@ -70,6 +71,7 @@
/**
* Callback representing that a media object [PlaybackState] has changed.
+ *
* @param key Media control unique identifier
* @param state The new [PlaybackState]
*/
@@ -77,6 +79,7 @@
/**
* Callback representing that the [MediaSession] for an active control has been destroyed
+ *
* @param key Media control unique identifier
*/
lateinit var sessionCallback: (String) -> Unit
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
index 2d10b82..92e0c85 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
@@ -37,6 +37,7 @@
import com.android.systemui.media.controls.models.player.MediaData
import com.android.systemui.media.controls.pipeline.MediaDataManager
import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.settings.UserTracker
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.Utils
@@ -63,7 +64,8 @@
private val tunerService: TunerService,
private val mediaBrowserFactory: ResumeMediaBrowserFactory,
dumpManager: DumpManager,
- private val systemClock: SystemClock
+ private val systemClock: SystemClock,
+ private val mediaFlags: MediaFlags,
) : MediaDataManager.Listener, Dumpable {
private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
@@ -231,7 +233,11 @@
mediaBrowser = null
}
// If we don't have a resume action, check if we haven't already
- if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession()) {
+ val isEligibleForResume =
+ data.isLocalSession() ||
+ (mediaFlags.isRemoteResumeAllowed() &&
+ data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
+ if (data.resumeAction == null && !data.hasCheckedForResume && isEligibleForResume) {
// TODO also check for a media button receiver intended for restarting (b/154127084)
Log.d(TAG, "Checking for service component for " + data.packageName)
val pm = context.packageManager
@@ -291,6 +297,7 @@
/**
* Add the component to the saved list of media browser services, checking for duplicates and
* removing older components that exceed the maximum limit
+ *
* @param componentName
*/
private fun updateResumptionList(componentName: ComponentName) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
index 335ce1d..095cf09 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
@@ -52,10 +52,12 @@
* event.
*
* @param isBrowserConnected true if there's a currently connected
+ *
* ```
* [android.media.browse.MediaBrowser] and false otherwise.
* @param componentName
* ```
+ *
* the component name for the [ResumeMediaBrowser] that triggered this log.
*/
fun logSessionDestroyed(isBrowserConnected: Boolean, componentName: ComponentName) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
index d2793bc..f5cc043 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
@@ -24,10 +24,12 @@
* and conflicts due to media notifications arriving at any time during an animation. It does this
* in two parts.
* - Exit animations fired as a result of user input are tracked. When these are running, any
+ *
* ```
* bind actions are delayed until the animation completes (and then fired in sequence).
* ```
* - Continuous animations are tracked using their rebind id. Later calls using the same
+ *
* ```
* rebind id will be totally ignored to prevent the continuous animation from restarting.
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index 4827a16..2b42604 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -201,7 +201,9 @@
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorSecondary),
::textSecondaryFromScheme
- ) { textSecondary -> mediaViewHolder.artistText.setTextColor(textSecondary) }
+ ) { textSecondary ->
+ mediaViewHolder.artistText.setTextColor(textSecondary)
+ }
val textTertiary =
animatingColorTransitionFactory(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
index 9f86cd8..3669493 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
@@ -159,6 +159,7 @@
/**
* Cross fade background.
+ *
* @see setTintList
* @see backgroundColor
*/
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index 6cf051a..680a8b6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -853,10 +853,12 @@
* @param startLocation the start location of our state or -1 if this is directly set
* @param endLocation the ending location of our state.
* @param progress the progress of the transition between startLocation and endlocation. If
+ *
* ```
* this is not a guided transformation, this will be 1.0f
* @param immediately
* ```
+ *
* should this state be applied immediately, canceling all animations?
*/
fun setCurrentState(
@@ -1100,17 +1102,17 @@
*
* @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN)
* @param instanceId id to uniquely identify a card, e.g. each headphone generates a new
- * instanceId
+ * instanceId
* @param uid uid for the application that media comes from
* @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when
- * the event happened
+ * the event happened
* @param interactedSubcardRank the rank for interacted media item for recommendation card, -1
- * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
+ * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
* @param interactedSubcardCardinality how many media items were shown to the user when there is
- * user interaction
+ * user interaction
* @param rank the rank for media card in the media carousel, starting from 0
* @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency
- * between headphone connection to sysUI displays media recommendation card
+ * between headphone connection to sysUI displays media recommendation card
* @param isSwipeToDismiss whether is to log swipe-to-dismiss event
*/
fun logSmartspaceCardReported(
@@ -1371,6 +1373,7 @@
/**
* Removes media player given the key.
+ *
* @param isDismissed determines whether the media player is removed from the carousel.
*/
fun removeMediaPlayer(key: String, isDismissed: Boolean = false) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index 66f12d6..7fc7bdb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -28,7 +28,6 @@
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
-import android.util.Log
import android.util.MathUtils
import android.view.View
import android.view.ViewGroup
@@ -418,8 +417,8 @@
* Calculate the alpha of the view when given a cross-fade progress.
*
* @param crossFadeProgress The current cross fade progress. 0.5f means it's just switching
- * between the start and the end location and the content is fully faded, while 0.75f means that
- * we're halfway faded in again in the target state.
+ * between the start and the end location and the content is fully faded, while 0.75f means
+ * that we're halfway faded in again in the target state.
*/
private fun calculateAlphaFromCrossFade(crossFadeProgress: Float): Float {
if (crossFadeProgress <= 0.5f) {
@@ -629,6 +628,7 @@
*
* @param forceNoAnimation optional parameter telling the system not to animate
* @param forceStateUpdate optional parameter telling the system to update transition state
+ *
* ```
* even if location did not change
* ```
@@ -944,7 +944,7 @@
/**
* @return the current transformation progress if we're in a guided transformation and -1
- * otherwise
+ * otherwise
*/
private fun getTransformationProgress(): Float {
if (skipQqsOnExpansion) {
@@ -1055,17 +1055,6 @@
// This will either do a full layout pass and remeasure, or it will bypass
// that and directly set the mediaFrame's bounds within the premeasured host.
targetHost.addView(mediaFrame)
-
- if (mediaFrame.childCount > 0) {
- val child = mediaFrame.getChildAt(0)
- if (mediaFrame.height < child.height) {
- Log.wtf(
- TAG,
- "mediaFrame height is too small for child: " +
- "${mediaFrame.height} vs ${child.height}"
- )
- }
- }
}
if (isCrossFadeAnimatorRunning) {
// When cross-fading with an animation, we only notify the media carousel of the
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
index 455b7de..be570b4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
@@ -126,6 +126,7 @@
* remeasurings later on.
*
* @param location the location this host name has. Used to identify the host during
+ *
* ```
* transitions.
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index b9b0459..0788e61 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -348,14 +348,17 @@
* bottom of UMO reach the bottom of this group It will change to alpha 1.0 when the visible
* bottom of UMO reach the top of the group below e.g.Album title, artist title and play-pause
* button will change alpha together.
+ *
* ```
* And their alpha becomes 1.0 when the visible bottom of UMO reach the top of controls,
* including progress bar, next button, previous button
* ```
+ *
* widgetGroupIds: a group of widgets have same state during UMO is squished,
* ```
* e.g. Album title, artist title and play-pause button
* ```
+ *
* groupEndPosition: the height of UMO, when the height reaches this value,
* ```
* widgets in this group should have 1.0 as alpha
@@ -363,6 +366,7 @@
* visible when the height of UMO reaches the top of controls group
* (progress bar, previous button and next button)
* ```
+ *
* squishedViewState: hold the widgetState of each widget, which will be modified
* squishFraction: the squishFraction of UMO
*/
@@ -665,7 +669,7 @@
*
* @param location Target
* @param locationWhenHidden Location that will be used when the target is not
- * [MediaHost.visible]
+ * [MediaHost.visible]
* @return State require for executing a transition, and also the respective [MediaHost].
*/
private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index c3fa76e..9bc66f6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -61,4 +61,7 @@
/** If true, do not automatically dismiss the recommendation card */
fun isPersistentSsCardEnabled() = featureFlags.isEnabled(Flags.MEDIA_RETAIN_RECOMMENDATIONS)
+
+ /** Check whether we allow remote media to generate resume controls */
+ fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index b71a9193..9928c4f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -16,10 +16,6 @@
package com.android.systemui.media.dialog;
-import static android.media.RouteListingPreference.Item.SUBTEXT_AD_ROUTING_DISALLOWED;
-import static android.media.RouteListingPreference.Item.SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED;
-import static android.media.RouteListingPreference.Item.SUBTEXT_SUBSCRIPTION_REQUIRED;
-
import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_GO_TO_APP;
import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_NONE;
import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER;
@@ -344,7 +340,7 @@
updateDeviceStatusIcon(deviceStatusIcon);
mStatusIcon.setVisibility(View.VISIBLE);
}
- updateTwoLineLayoutContentAlpha(
+ updateSingleLineLayoutContentAlpha(
updateClickActionBasedOnSelectionBehavior(device)
? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
} else {
@@ -368,6 +364,12 @@
mStatusIcon.setAlpha(alphaValue);
}
+ private void updateSingleLineLayoutContentAlpha(float alphaValue) {
+ mTitleIcon.setAlpha(alphaValue);
+ mTitleText.setAlpha(alphaValue);
+ mStatusIcon.setAlpha(alphaValue);
+ }
+
private void updateEndClickAreaAsSessionEditing(MediaDevice device) {
mEndClickIcon.setOnClickListener(null);
mEndTouchArea.setOnClickListener(null);
@@ -535,11 +537,12 @@
@DoNotInline
static Drawable getDeviceStatusIconBasedOnSelectionBehavior(MediaDevice device,
Context context) {
- switch (device.getSubtext()) {
- case SUBTEXT_AD_ROUTING_DISALLOWED:
- case SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED:
+ switch (device.getSelectionBehavior()) {
+ case SELECTION_BEHAVIOR_NONE:
return context.getDrawable(R.drawable.media_output_status_failed);
- case SUBTEXT_SUBSCRIPTION_REQUIRED:
+ case SELECTION_BEHAVIOR_TRANSFER:
+ return null;
+ case SELECTION_BEHAVIOR_GO_TO_APP:
return context.getDrawable(R.drawable.media_output_status_help);
}
return null;
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 2aedd36..9203897 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -395,7 +395,6 @@
launchIntent.putExtra(EXTRA_ROUTE_ID, routeId);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mCallback.dismissDialog();
- mContext.startActivity(launchIntent);
mActivityStarter.startActivity(launchIntent, true, controller);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
index e35575b..b5b1f0f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
@@ -23,8 +23,6 @@
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.CommandQueue;
import javax.inject.Inject;
@@ -37,26 +35,19 @@
private final CommandQueue mCommandQueue;
private final MediaOutputDialogFactory mMediaOutputDialogFactory;
- private final FeatureFlags mFeatureFlags;
@Inject
public MediaOutputSwitcherDialogUI(
Context context,
CommandQueue commandQueue,
- MediaOutputDialogFactory mediaOutputDialogFactory,
- FeatureFlags featureFlags) {
+ MediaOutputDialogFactory mediaOutputDialogFactory) {
mCommandQueue = commandQueue;
mMediaOutputDialogFactory = mediaOutputDialogFactory;
- mFeatureFlags = featureFlags;
}
@Override
public void start() {
- if (mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_SHOW_API_ENABLED)) {
- mCommandQueue.addCallback(this);
- } else {
- Log.w(TAG, "Show media output switcher is not enabled.");
- }
+ mCommandQueue.addCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
index 720c44a..ee93c37 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
@@ -43,7 +43,7 @@
*
* @param appPackageName the package name of the app playing the media.
* @param onPackageNotFoundException a function run if a
- * [PackageManager.NameNotFoundException] occurs.
+ * [PackageManager.NameNotFoundException] occurs.
* @param isReceiver indicates whether the icon is displayed in a receiver view.
*/
fun getIconInfoFromPackageName(
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
index 7a77c47..01398cf 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
@@ -70,6 +70,8 @@
RECENT_IGNORE_UNAVAILABLE,
userTracker.userId,
backgroundExecutor
- ) { tasks -> continuation.resume(tasks) }
+ ) { tasks ->
+ continuation.resume(tasks)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 4db1da3..0dfb9b1 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -1007,7 +1007,11 @@
private void notifyNavigationBarSurface() {
ViewRootImpl viewRoot = mView.getViewRootImpl();
- SurfaceControl surface = viewRoot != null ? viewRoot.getSurfaceControl() : null;
+ SurfaceControl surface = viewRoot != null
+ && viewRoot.getSurfaceControl() != null
+ && viewRoot.getSurfaceControl().isValid()
+ ? viewRoot.getSurfaceControl()
+ : null;
mOverviewProxyService.onNavigationBarSurfaceChanged(surface);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index f3d6014..f28c275 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -28,6 +28,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
@@ -54,6 +55,7 @@
import android.view.MotionEvent;
import android.view.Surface;
import android.view.ViewConfiguration;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.window.BackEvent;
@@ -234,6 +236,7 @@
private boolean mLogGesture = false;
private boolean mInRejectedExclusion = false;
private boolean mIsOnLeftEdge;
+ private boolean mDeferSetIsOnLeftEdge;
private boolean mIsAttached;
private boolean mIsGesturalModeEnabled;
@@ -775,6 +778,19 @@
return true;
}
+ private boolean isValidTrackpadBackGesture(boolean isTrackpadEvent) {
+ if (!isTrackpadEvent) {
+ return false;
+ }
+ // for trackpad gestures, unless the whole screen is excluded region, 3-finger swipe
+ // gestures are allowed even if the cursor is in the excluded region.
+ WindowInsets windowInsets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+ Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars());
+ final Rect excludeBounds = mExcludeRegion.getBounds();
+ return !excludeBounds.contains(insets.left, insets.top, mDisplaySize.x - insets.right,
+ mDisplaySize.y - insets.bottom);
+ }
+
private boolean isWithinTouchRegion(int x, int y) {
// If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back
// gesture
@@ -878,7 +894,9 @@
// either the bouncer is showing or the notification panel is hidden
mInputEventReceiver.setBatchingEnabled(false);
if (isTrackpadEvent) {
- // TODO: show the back arrow based on the direction of the swipe.
+ // Since trackpad gestures don't have zones, this will be determined later by the
+ // direction of the gesture. {@code mIsOnLeftEdge} is set to false to begin with.
+ mDeferSetIsOnLeftEdge = true;
mIsOnLeftEdge = false;
} else {
mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
@@ -893,13 +911,14 @@
&& (isTrackpadEvent || isWithinInsets)
&& !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
- && (isTrackpadEvent || isWithinTouchRegion((int) ev.getX(), (int) ev.getY()));
+ && (isValidTrackpadBackGesture(isTrackpadEvent) || isWithinTouchRegion(
+ (int) ev.getX(), (int) ev.getY()));
if (mAllowGesture) {
mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
mEdgeBackPlugin.onMotionEvent(ev);
dispatchToBackAnimation(ev);
}
- if (mLogGesture) {
+ if (mLogGesture || isTrackpadEvent) {
mDownPoint.set(ev.getX(), ev.getY());
mEndPoint.set(-1, -1);
mThresholdCrossed = false;
@@ -907,9 +926,9 @@
// For debugging purposes, only log edge points
(isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format(
- "Gesture [%d,alw=%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
+ "Gesture [%d,alw=%B,%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
System.currentTimeMillis(), isTrackpadEvent, mAllowGesture, mIsOnLeftEdge,
- mIsBackGestureAllowed,
+ mDeferSetIsOnLeftEdge, mIsBackGestureAllowed,
QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisplaySize,
mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
} else if (mAllowGesture || mLogGesture) {
@@ -928,6 +947,14 @@
mLogGesture = false;
return;
} else if (action == MotionEvent.ACTION_MOVE) {
+ if (isTrackpadEvent && mDeferSetIsOnLeftEdge) {
+ // mIsOnLeftEdge is determined by the relative position between the down
+ // and the current motion event for trackpad gestures instead of zoning.
+ mIsOnLeftEdge = mEndPoint.x > mDownPoint.x;
+ mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
+ mDeferSetIsOnLeftEdge = false;
+ }
+
if ((ev.getEventTime() - ev.getDownTime()) > mLongPressTimeout) {
if (mAllowGesture) {
logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_LONG_PRESS);
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
index b5d757c..0f75f95 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
@@ -31,6 +31,7 @@
private val roleManager: RoleManager,
private val packageManager: PackageManager,
) {
+
fun resolveInfo(
entryPoint: NoteTaskEntryPoint? = null,
isInMultiWindowMode: Boolean = false,
@@ -38,7 +39,8 @@
): NoteTaskInfo? {
// TODO(b/267634412): Select UserHandle depending on where the user initiated note-taking.
val user = context.user
- val packageName = roleManager.getRoleHoldersAsUser(ROLE_NOTES, user).firstOrNull()
+ val packageName =
+ roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user).firstOrNull()
if (packageName.isNullOrEmpty()) return null
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index 3f4f8d5..fb3c0cb 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -15,6 +15,7 @@
*/
package com.android.systemui.notetask
+import android.view.KeyEvent
import androidx.annotation.VisibleForTesting
import com.android.systemui.statusbar.CommandQueue
import com.android.wm.shell.bubbles.Bubbles
@@ -35,7 +36,7 @@
val callbacks =
object : CommandQueue.Callbacks {
override fun handleSystemKey(keyCode: Int) {
- if (keyCode == NoteTaskController.NOTE_TASK_KEY_EVENT) {
+ if (keyCode == KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL) {
controller.showNoteTask(NoteTaskEntryPoint.TAIL_BUTTON)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index f16110d..ba8999c 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -51,7 +51,7 @@
featureFlags: FeatureFlags,
roleManager: RoleManager,
): Boolean {
- val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskInfoResolver.ROLE_NOTES)
+ val isRoleAvailable = roleManager.isRoleAvailable(RoleManager.ROLE_NOTES)
val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
return isRoleAvailable && isFeatureEnabled
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/OWNERS b/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
@@ -5,4 +5,6 @@
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
index 0a1d008..8ced4646 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
@@ -33,8 +33,8 @@
* launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
*
* @see <a
- * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
- * a custom shortcut activity</a>
+ * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
+ * a custom shortcut activity</a>
*/
class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
index 2b84bf8..80fce6a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -49,7 +49,7 @@
return Intent(context, LaunchNoteTaskActivity::class.java).apply {
// Intent's action must be set in shortcuts, or an exception will be thrown.
// TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
- action = NoteTaskController.ACTION_CREATE_NOTE
+ action = Intent.ACTION_CREATE_NOTE
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 2522e1c..7a42642 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -154,6 +154,7 @@
private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
private final Intent mOpenBatterySaverSettings =
settings(Settings.ACTION_BATTERY_SAVER_SETTINGS);
+ private final boolean mUseExtraSaverConfirmation;
private int mBatteryLevel;
private int mBucket;
@@ -197,6 +198,8 @@
mDialogLaunchAnimator = dialogLaunchAnimator;
mUiEventLogger = uiEventLogger;
mUserTracker = userTracker;
+ mUseExtraSaverConfirmation =
+ mContext.getResources().getBoolean(R.bool.config_extra_battery_saver_confirmation);
}
@Override
@@ -644,7 +647,7 @@
}
private void showStartSaverConfirmation(Bundle extras) {
- if (mSaverConfirmation != null) return;
+ if (mSaverConfirmation != null || mUseExtraSaverConfirmation) return;
final SystemUIDialog d = new SystemUIDialog(mContext);
final boolean confirmOnly = extras.getBoolean(BatterySaverUtils.EXTRA_CONFIRM_TEXT_ONLY);
final int batterySaverTriggerMode =
@@ -679,6 +682,10 @@
resolver,
Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
1, mUserTracker.getUserId());
+ Secure.putIntForUser(
+ resolver,
+ Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED,
+ 1, mUserTracker.getUserId());
});
} else {
d.setTitle(R.string.battery_saver_confirmation_title);
diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
index ff3ec72..d40112f 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
@@ -26,8 +26,7 @@
@Module
interface QRCodeScannerModule {
- /**
- */
+ /** */
@Binds
@IntoMap
@StringKey(QRCodeScannerTile.TILE_SPEC)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index e86bd7a..9f93e49 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -76,7 +76,8 @@
this(tileServices, handler, userTracker, new TileLifecycleManager(handler,
tileServices.getContext(), tileServices,
new PackageManagerAdapter(tileServices.getContext()), broadcastDispatcher,
- new Intent().setComponent(component), userTracker.getUserHandle()));
+ new Intent(TileService.ACTION_QS_TILE).setComponent(component),
+ userTracker.getUserHandle()));
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
index 03bb7a0..8387c1d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
@@ -71,8 +71,8 @@
/**
* Show the device monitoring dialog, expanded from [expandable] if it's not null.
*
- * Important: [quickSettingsContext] *must* be the [Context] associated to the [Quick Settings
- * fragment][com.android.systemui.qs.QSFragment].
+ * Important: [quickSettingsContext] *must* be the [Context] associated to the
+ * [Quick Settings fragment][com.android.systemui.qs.QSFragment].
*/
fun showDeviceMonitoringDialog(quickSettingsContext: Context, expandable: Expandable?)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
index fbf32b3..f170ac1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
@@ -196,9 +196,9 @@
* Observe the device monitoring dialog requests and show the dialog accordingly. This function
* will suspend indefinitely and will need to be cancelled to stop observing.
*
- * Important: [quickSettingsContext] must be the [Context] associated to the [Quick Settings
- * fragment][com.android.systemui.qs.QSFragment], and the call to this function must be
- * cancelled when that fragment is destroyed.
+ * Important: [quickSettingsContext] must be the [Context] associated to the
+ * [Quick Settings fragment][com.android.systemui.qs.QSFragment], and the call to this function
+ * must be cancelled when that fragment is destroyed.
*/
suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) {
footerActionsInteractor.deviceMonitoringDialogRequests.collect {
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index dd21be9..30509e2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -124,8 +124,9 @@
/**
* Starts screen capture after some countdown
+ *
* @param captureTarget target to capture (could be e.g. a task) or null to record the whole
- * screen
+ * screen
*/
private fun requestScreenCapture(captureTarget: MediaProjectionCaptureTarget?) {
val userContext = userContextProvider.userContext
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
index 310baaf..a8f99be 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
@@ -70,7 +70,7 @@
/**
* @return an ACTION_EDIT intent for the given URI, directed to config_screenshotEditor if
- * available.
+ * available.
*/
fun createEditIntent(uri: Uri, context: Context): Intent {
val editIntent = Intent(Intent.ACTION_EDIT)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
index 1b728b8..236213c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
@@ -44,7 +44,7 @@
/**
* @return a populated WorkProfileFirstRunData object if a work profile first run message should
- * be shown
+ * be shown
*/
fun onScreenshotTaken(userHandle: UserHandle?): WorkProfileFirstRunData? {
if (userHandle == null) return null
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index 287e810..33a3125 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.content.pm.UserInfo
import android.os.UserHandle
+import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
/**
@@ -67,14 +68,25 @@
interface Callback {
/**
+ * Same as {@link onUserChanging(Int, Context, CountDownLatch)} but the latch will be
+ * auto-decremented after the completion of this method.
+ */
+ @JvmDefault
+ fun onUserChanging(newUser: Int, userContext: Context) {}
+
+ /**
* Notifies that the current user is being changed.
* Override this method to run things while the screen is frozen for the user switch.
* Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
* screen further. Please be aware that code executed in this callback will lengthen the
- * user switch duration.
+ * user switch duration. When overriding this method, countDown() MUST be called on the
+ * latch once execution is complete.
*/
@JvmDefault
- fun onUserChanging(newUser: Int, userContext: Context) {}
+ fun onUserChanging(newUser: Int, userContext: Context, latch: CountDownLatch) {
+ onUserChanging(newUser, userContext)
+ latch.countDown()
+ }
/**
* Notifies that the current user has changed.
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 3a5d0a7..0b2ae05 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -182,9 +182,22 @@
Log.i(TAG, "Switching to user $newUserId")
setUserIdInternal(newUserId)
- notifySubscribers {
- onUserChanging(newUserId, userContext)
- }.await()
+
+ val list = synchronized(callbacks) {
+ callbacks.toList()
+ }
+ val latch = CountDownLatch(list.size)
+ list.forEach {
+ val callback = it.callback.get()
+ if (callback != null) {
+ it.executor.execute {
+ callback.onUserChanging(userId, userContext, latch)
+ }
+ } else {
+ latch.countDown()
+ }
+ }
+ latch.await()
}
@WorkerThread
@@ -224,25 +237,18 @@
}
}
- private inline fun notifySubscribers(
- crossinline action: UserTracker.Callback.() -> Unit
- ): CountDownLatch {
+ private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) {
val list = synchronized(callbacks) {
callbacks.toList()
}
- val latch = CountDownLatch(list.size)
list.forEach {
if (it.callback.get() != null) {
it.executor.execute {
it.callback.get()?.action()
- latch.countDown()
}
- } else {
- latch.countDown()
}
}
- return latch
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index e75320a..b1987c1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -23,6 +23,7 @@
import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
@@ -71,6 +72,7 @@
import android.provider.Settings;
import android.transition.ChangeBounds;
import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.transition.TransitionValues;
@@ -98,6 +100,7 @@
import androidx.constraintlayout.widget.ConstraintSet;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.SystemBarUtils;
@@ -365,6 +368,7 @@
private final NotificationGutsManager mGutsManager;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final QuickSettingsController mQsController;
+ private final InteractionJankMonitor mInteractionJankMonitor;
private long mDownTime;
private boolean mTouchSlopExceededBeforeDown;
@@ -656,6 +660,19 @@
step.getTransitionState() == TransitionState.RUNNING;
};
+ private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
+ new TransitionListenerAdapter() {
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mInteractionJankMonitor.end(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+ }
+ };
+
@Inject
public NotificationPanelViewController(NotificationPanelView view,
@Main Handler handler,
@@ -720,6 +737,7 @@
NotificationStackSizeCalculator notificationStackSizeCalculator,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
ShadeTransitionController shadeTransitionController,
+ InteractionJankMonitor interactionJankMonitor,
SystemClock systemClock,
KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
@@ -734,6 +752,7 @@
DumpManager dumpManager,
KeyguardLongPressViewModel keyguardLongPressViewModel,
KeyguardInteractor keyguardInteractor) {
+ mInteractionJankMonitor = interactionJankMonitor;
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
public void onKeyguardFadingAwayChanged() {
@@ -1555,6 +1574,7 @@
int statusConstraint = shouldBeCentered ? PARENT_ID : R.id.qs_edge_guideline;
constraintSet.connect(R.id.keyguard_status_view, END, statusConstraint, END);
if (animate) {
+ mInteractionJankMonitor.begin(mView, CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
ChangeBounds transition = new ChangeBounds();
if (mSplitShadeEnabled) {
// Excluding media from the transition on split-shade, as it doesn't transition
@@ -1578,6 +1598,7 @@
// The clock container can sometimes be null. If it is, just fall back to the
// old animation rather than setting up the custom animations.
if (clockContainerView == null || clockContainerView.getChildCount() == 0) {
+ transition.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(
mNotificationContainerParent, transition);
} else {
@@ -1596,10 +1617,11 @@
adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION);
adapter.addTarget(clockView);
set.addTransition(adapter);
-
+ set.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(mNotificationContainerParent, set);
}
} else {
+ transition.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(
mNotificationContainerParent, transition);
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index a1767cc..f4b1cc5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -107,7 +107,7 @@
*
* @param fraction the fraction from the expansion in [0, 1]
* @param expanded whether the panel is currently expanded; this is independent from the
- * fraction as the panel also might be expanded if the fraction is 0.
+ * fraction as the panel also might be expanded if the fraction is 0.
* @param tracking whether we're currently tracking the user's gesture.
*/
fun onPanelExpansionChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index 37773e9..b79f32a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -70,9 +70,9 @@
*
* [header] is a [MotionLayout] that has two transitions:
* * [HEADER_TRANSITION_ID]: [QQS_HEADER_CONSTRAINT] <-> [QS_HEADER_CONSTRAINT] for portrait
- * handheld device configuration.
+ * handheld device configuration.
* * [LARGE_SCREEN_HEADER_TRANSITION_ID]: [LARGE_SCREEN_HEADER_CONSTRAINT] for all other
- * configurations
+ * configurations
*/
@CentralSurfacesScope
class ShadeHeaderController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
index 62c225b..df8c6ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
@@ -148,7 +148,8 @@
qsDragFraction: $qsTransitionFraction
qsSquishFraction: $qsSquishTransitionFraction
isTransitioningToFullShade: $isTransitioningToFullShade
- """.trimIndent()
+ """
+ .trimIndent()
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f0d064b..9a9503c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -572,8 +572,7 @@
entry.setGroupExpansionChanging(true)
userId = entry.sbn.userId
}
- var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
- lockScreenUserManager.getCurrentUserId()) ||
+ var fullShadeNeedsBouncer = (
!lockScreenUserManager.shouldShowLockscreenNotifications() ||
falsingCollector.shouldEnforceBouncer())
if (keyguardBypassController.bypassEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
index 42b874f..7297ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
@@ -74,7 +74,7 @@
/**
* @return a context with the MCC/MNC [Configuration] values corresponding to this
- * subscriptionId
+ * subscriptionId
*/
fun getMobileContextForSub(subId: Int, context: Context): Context {
if (demoModeController.isInDemoMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
index 64b7ac9..5fa83ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
@@ -39,6 +39,7 @@
* - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
* - Only schedules a single event, and throws away lowest priority events
* ```
+ *
* There are 4 basic stages of animation at play here:
* ```
* 1. System chrome animation OUT
@@ -46,6 +47,7 @@
* 3. Chip animation OUT; potentially into a dot
* 4. System chrome animation IN
* ```
+ *
* Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
* chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
* their respective views based on the progress of the animator. Interpolation differences TBD
@@ -168,7 +170,7 @@
* 3. Update the scheduler state so that clients know where we are
* 4. Maybe: provide scaffolding such as: dot location, margins, etc
* 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
- * collect all of the animators and run them together.
+ * collect all of the animators and run them together.
*/
private fun runChipAnimation() {
statusBarWindowController.setForceStatusBarVisible(true)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index f395bea..82c5ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -334,9 +334,9 @@
}
val ssView = plugin.getView(parent)
+ configPlugin?.let { ssView.registerConfigProvider(it) }
ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
ssView.registerDataProvider(plugin)
- configPlugin?.let { ssView.registerConfigProvider(it) }
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 0a5e986..11582d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -29,7 +29,6 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.app.SynchronousUserSwitchObserver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -52,7 +51,9 @@
import com.android.systemui.CoreStartable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
@@ -73,6 +74,8 @@
private final Context mContext;
private final Handler mHandler = new Handler();
+ private final UserTracker mUserTracker;
+ private final Executor mMainExecutor;
private final Executor mUiBgExecutor;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final CommandQueue mCommandQueue;
@@ -82,10 +85,14 @@
public InstantAppNotifier(
Context context,
CommandQueue commandQueue,
+ UserTracker userTracker,
+ @Main Executor mainExecutor,
@UiBackground Executor uiBgExecutor,
KeyguardStateController keyguardStateController) {
mContext = context;
mCommandQueue = commandQueue;
+ mUserTracker = userTracker;
+ mMainExecutor = mainExecutor;
mUiBgExecutor = uiBgExecutor;
mKeyguardStateController = keyguardStateController;
}
@@ -93,11 +100,7 @@
@Override
public void start() {
// listen for user / profile change.
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
- } catch (RemoteException e) {
- // Ignore
- }
+ mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
mCommandQueue.addCallback(this);
mKeyguardStateController.addCallback(this);
@@ -129,13 +132,10 @@
updateForegroundInstantApps();
}
- private final SynchronousUserSwitchObserver mUserSwitchListener =
- new SynchronousUserSwitchObserver() {
+ private final UserTracker.Callback mUserSwitchListener =
+ new UserTracker.Callback() {
@Override
- public void onUserSwitching(int newUserId) throws RemoteException {}
-
- @Override
- public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.post(
() -> {
updateForegroundInstantApps();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 7e53d54..8874f59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,6 +18,7 @@
import android.animation.ObjectAnimator
import android.util.FloatProperty
+import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
@@ -302,29 +303,29 @@
// the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
// See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+ this.state = newState
+ return
}
if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
+ this.state = newState
return
}
if (overrideDozeAmountIfBypass()) {
+ this.state = newState
return
}
maybeClearDozeAmountOverrideHidingNotifs()
- if (bypassController.bypassEnabled &&
- newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
- (!statusBarStateController.isDozing || shouldAnimateVisibility())) {
- // We're leaving shade locked. Let's animate the notifications away
- setNotificationsVisible(visible = true, increaseSpeed = false, animate = false)
- setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
- }
-
this.state = newState
}
+ @VisibleForTesting
+ val statusBarState: Int
+ get() = state
+
override fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
val collapsedEnough = event.fraction <= 0.9f
if (collapsedEnough != this.collapsedEnoughToHide) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
index 4464531..88d9ffc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
@@ -13,7 +13,7 @@
package com.android.systemui.statusbar.notification
-import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.log.dagger.NotificationLockscreenLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.statusbar.StatusBarState
@@ -21,7 +21,12 @@
class NotificationWakeUpCoordinatorLogger
@Inject
-constructor(@NotificationLog private val buffer: LogBuffer) {
+constructor(@NotificationLockscreenLog private val buffer: LogBuffer) {
+ private var lastSetDozeAmountLogWasFractional = false
+ private var lastSetDozeAmountLogState = -1
+ private var lastSetDozeAmountLogSource = "undefined"
+ private var lastOnDozeAmountChangedLogWasFractional = false
+
fun logSetDozeAmount(
linear: Float,
eased: Float,
@@ -29,6 +34,20 @@
state: Int,
changed: Boolean,
) {
+ // Avoid logging on every frame of the animation if important values are not changing
+ val isFractional = linear != 1f && linear != 0f
+ if (
+ lastSetDozeAmountLogWasFractional &&
+ isFractional &&
+ lastSetDozeAmountLogState == state &&
+ lastSetDozeAmountLogSource == source
+ ) {
+ return
+ }
+ lastSetDozeAmountLogWasFractional = isFractional
+ lastSetDozeAmountLogState = state
+ lastSetDozeAmountLogSource = source
+
buffer.log(
TAG,
DEBUG,
@@ -66,6 +85,10 @@
}
fun logOnDozeAmountChanged(linear: Float, eased: Float) {
+ // Avoid logging on every frame of the animation when values are fractional
+ val isFractional = linear != 1f && linear != 0f
+ if (lastOnDozeAmountChangedLogWasFractional && isFractional) return
+ lastOnDozeAmountChangedLogWasFractional = isFractional
buffer.log(
TAG,
DEBUG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index a35617c..6deef2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -315,6 +315,7 @@
/**
* State object for a `Roundable` class.
+ *
* @param targetView Will handle the [AnimatableProperty]
* @param roundable Target of the radius animation
* @param maxRadius Max corner radius in pixels
@@ -436,7 +437,6 @@
* This is the most convenient way to define a new [SourceType].
*
* For example:
- *
* ```kotlin
* private val SECTION = SourceType.from("Section")
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
index 1fccf82..0a9dddc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
@@ -46,6 +46,7 @@
/**
* Visits every entry and its children to mark the dismissible entries.
+ *
* @param markedKeys set to store the marked entry keys
* @param entries to visit
* @param isLocked the locked state of the device
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 2868116..92c5b63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -211,7 +211,11 @@
public void onViewAttachedToWindow(View v) {
mConfigurationController.addCallback(mConfigurationListener);
mZenModeController.addCallback(mZenModeControllerCallback);
- mBarState = mStatusBarStateController.getState();
+ final int newBarState = mStatusBarStateController.getState();
+ if (newBarState != mBarState) {
+ mStateListener.onStateChanged(newBarState);
+ mStateListener.onStatePostChange();
+ }
mStatusBarStateController.addCallback(
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index aaf9300..c6f56d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -251,13 +251,13 @@
|| (isFastNonDismissGesture && isAbleToShowMenu);
int menuSnapTarget = menuRow.getMenuSnapTarget();
boolean isNonFalseMenuRevealingGesture =
- !isFalseGesture() && isMenuRevealingGestureAwayFromMenu;
+ isMenuRevealingGestureAwayFromMenu && !isFalseGesture();
if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture)
&& menuSnapTarget != 0) {
// Menu has not been snapped to previously and this is menu revealing gesture
snapOpen(animView, menuSnapTarget, velocity);
menuRow.onSnapOpen();
- } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
+ } else if (isDismissGesture && !gestureTowardsMenu) {
dismiss(animView, velocity);
menuRow.onDismiss();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index 548d1a1..8b6d6a4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -25,9 +25,10 @@
/**
* This method looks for views that can be rounded (and implement [Roundable]) during a
* notification swipe.
+ *
* @return The [Roundable] targets above/below the [viewSwiped] (if available). The
- * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
- * no above/below notification or the notification is not part of the same section.
+ * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
+ * no above/below notification or the notification is not part of the same section.
*/
fun findRoundableTargets(
viewSwiped: ExpandableNotificationRow,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index b166446..d6dc671 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -2254,10 +2254,10 @@
pw.println("Current Status Bar state:");
pw.println(" mExpandedVisible=" + mShadeController.isExpandedVisible());
pw.println(" mDisplayMetrics=" + mDisplayMetrics);
- pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
- pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller)
- + " scroll " + mStackScroller.getScrollX()
+ pw.print(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
+ pw.print(" scroll " + mStackScroller.getScrollX()
+ "," + mStackScroller.getScrollY());
+ pw.println(" translationX " + mStackScroller.getTranslationX());
}
pw.print(" mInteractingWindows="); pw.println(mInteractingWindows);
@@ -3799,6 +3799,9 @@
} else {
mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
}
+ // This will cancel the keyguardFadingAway animation if it is running. We need to do
+ // this as otherwise it can remain pending and leave keyguard in a weird state.
+ mUnlockScrimCallback.onCancelled();
} else if (mBouncerShowing && !unlocking) {
// Bouncer needs the front scrim when it's on top of an activity,
// tapping on a notification, editing QS or being dismissed by
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6c532a5..e6b76ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,8 +22,6 @@
import android.app.ActivityTaskManager;
import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
-import android.app.IActivityManager;
-import android.app.SynchronousUserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -134,7 +132,6 @@
private final NextAlarmController mNextAlarmController;
private final AlarmManager mAlarmManager;
private final UserInfoController mUserInfoController;
- private final IActivityManager mIActivityManager;
private final UserManager mUserManager;
private final UserTracker mUserTracker;
private final DevicePolicyManager mDevicePolicyManager;
@@ -149,6 +146,7 @@
private final KeyguardStateController mKeyguardStateController;
private final LocationController mLocationController;
private final PrivacyItemController mPrivacyItemController;
+ private final Executor mMainExecutor;
private final Executor mUiBgExecutor;
private final SensorPrivacyController mSensorPrivacyController;
private final RecordingController mRecordingController;
@@ -168,16 +166,17 @@
@Inject
public PhoneStatusBarPolicy(StatusBarIconController iconController,
CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
- @UiBackground Executor uiBgExecutor, @Main Looper looper, @Main Resources resources,
- CastController castController, HotspotController hotspotController,
- BluetoothController bluetoothController, NextAlarmController nextAlarmController,
- UserInfoController userInfoController, RotationLockController rotationLockController,
- DataSaverController dataSaverController, ZenModeController zenModeController,
+ @Main Executor mainExecutor, @UiBackground Executor uiBgExecutor, @Main Looper looper,
+ @Main Resources resources, CastController castController,
+ HotspotController hotspotController, BluetoothController bluetoothController,
+ NextAlarmController nextAlarmController, UserInfoController userInfoController,
+ RotationLockController rotationLockController, DataSaverController dataSaverController,
+ ZenModeController zenModeController,
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController,
LocationController locationController,
- SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
- AlarmManager alarmManager, UserManager userManager, UserTracker userTracker,
+ SensorPrivacyController sensorPrivacyController, AlarmManager alarmManager,
+ UserManager userManager, UserTracker userTracker,
DevicePolicyManager devicePolicyManager, RecordingController recordingController,
@Nullable TelecomManager telecomManager, @DisplayId int displayId,
@Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
@@ -195,7 +194,6 @@
mNextAlarmController = nextAlarmController;
mAlarmManager = alarmManager;
mUserInfoController = userInfoController;
- mIActivityManager = iActivityManager;
mUserManager = userManager;
mUserTracker = userTracker;
mDevicePolicyManager = devicePolicyManager;
@@ -208,6 +206,7 @@
mPrivacyItemController = privacyItemController;
mSensorPrivacyController = sensorPrivacyController;
mRecordingController = recordingController;
+ mMainExecutor = mainExecutor;
mUiBgExecutor = uiBgExecutor;
mTelecomManager = telecomManager;
mRingerModeTracker = ringerModeTracker;
@@ -256,11 +255,7 @@
mRingerModeTracker.getRingerModeInternal().observeForever(observer);
// listen for user / profile change.
- try {
- mIActivityManager.registerUserSwitchObserver(mUserSwitchListener, TAG);
- } catch (RemoteException e) {
- // Ignore
- }
+ mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
// TTY status
updateTTY();
@@ -555,15 +550,15 @@
});
}
- private final SynchronousUserSwitchObserver mUserSwitchListener =
- new SynchronousUserSwitchObserver() {
+ private final UserTracker.Callback mUserSwitchListener =
+ new UserTracker.Callback() {
@Override
- public void onUserSwitching(int newUserId) throws RemoteException {
+ public void onUserChanging(int newUser, Context userContext) {
mHandler.post(() -> mUserInfoController.reloadUserInfo());
}
@Override
- public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.post(() -> {
updateAlarm();
updateManagedProfile();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
index 8c82fba..f4e3eab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
@@ -45,7 +45,7 @@
* 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig]
* 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config]
* 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly
- * updated when a new carrier config comes down
+ * updated when a new carrier config comes down
*/
class SystemUiCarrierConfig
internal constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index b3d5b1e..53a208c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -353,8 +353,8 @@
* True if the checked subId is in the list of current subs or the active mobile data subId
*
* @param checkedSubs the list to validate [subId] against. To invalidate the cache, pass in the
- * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
- * current known subscriptions
+ * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
+ * current known subscriptions
*/
private fun checkSub(subId: Int, checkedSubs: List<SubscriptionModel>): Boolean {
if (activeMobileDataSubscriptionId.value == subId) return true
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 7b0f952..4caf2b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -92,7 +92,8 @@
* 1. The default network name, if one is configured
* 2. A derived name based off of the intent [ACTION_SERVICE_PROVIDERS_UPDATED]
* 3. Or, in the case where the repository sends us the default network name, we check for an
- * override in [connectionInfo.operatorAlphaShort], a value that is derived from [ServiceState]
+ * override in [connectionInfo.operatorAlphaShort], a value that is derived from
+ * [ServiceState]
*/
val networkName: StateFlow<NetworkNameModel>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
index 24cd930..8e103f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
@@ -25,7 +25,7 @@
* allows the mobile icon to change some view parameters at different locations
*
* @param commonImpl for convenience, this class wraps a base interface that can provides all of the
- * common implementations between locations. See [MobileIconViewModel]
+ * common implementations between locations. See [MobileIconViewModel]
*/
abstract class LocationBasedMobileViewModel(
val commonImpl: MobileIconViewModelCommon,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
index e0e0ed7..b129617 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
@@ -41,7 +41,6 @@
* or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
* way, downstream clients can all consist of real implementations and not care about which
* repository is responsible for the data. Graphically:
- *
* ```
* RealRepository
* │
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
index bdb656b..1e223b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
@@ -146,7 +146,7 @@
*
* @param guestUserId id of the guest user to remove
* @param targetUserId id of the user to switch to after guest is removed. If
- * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
+ * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
*/
fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
userInteractor.removeGuestUser(
@@ -160,9 +160,9 @@
*
* @param guestUserId user id of the guest user to exit
* @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
- * target user id is not known
+ * target user id is not known
* @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
- * only if its ephemeral, else keep guest
+ * only if its ephemeral, else keep guest
*/
fun exitGuestUser(guestUserId: Int, targetUserId: Int, forceRemoveGuestOnExit: Boolean) {
userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/OWNERS b/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
@@ -5,4 +5,6 @@
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
index 4e27ce6..030c54f 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
@@ -22,6 +22,7 @@
import android.hardware.BatteryState
import android.hardware.input.InputManager
import android.hardware.input.InputSettings
+import android.os.Build
import android.os.Handler
import android.util.ArrayMap
import android.util.Log
@@ -398,12 +399,11 @@
companion object {
val TAG = StylusManager::class.simpleName.orEmpty()
- const val DEBUG = false
}
}
private inline fun logDebug(message: () -> String) {
- if (StylusManager.DEBUG) {
+ if (Build.IS_DEBUGGABLE) {
Log.d(StylusManager.TAG, message())
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index ec0a6e7..21b0efa 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -26,6 +26,7 @@
import android.content.IntentFilter
import android.hardware.BatteryState
import android.hardware.input.InputManager
+import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.UserHandle
@@ -109,6 +110,10 @@
inputDeviceId = deviceId
batteryCapacity = batteryState.capacity
+ logDebug {
+ "Updating notification battery state to $batteryCapacity " +
+ "for InputDevice $deviceId."
+ }
refresh()
}
}
@@ -125,12 +130,14 @@
handler.post updateSuppressed@{
if (suppressed == suppress) return@updateSuppressed
+ logDebug { "Updating notification suppression to $suppress." }
suppressed = suppress
refresh()
}
}
private fun hideNotification() {
+ logDebug { "Cancelling USI low battery notification." }
instanceId = null
notificationManager.cancel(USI_NOTIFICATION_ID)
}
@@ -153,6 +160,7 @@
.setAutoCancel(true)
.build()
+ logDebug { "Show or update USI low battery notification at $batteryCapacity." }
logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN)
notificationManager.notify(USI_NOTIFICATION_ID, notification)
}
@@ -180,10 +188,12 @@
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
ACTION_DISMISSED_LOW_BATTERY -> {
+ logDebug { "USI low battery notification dismissed." }
logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED)
updateSuppression(true)
}
ACTION_CLICKED_LOW_BATTERY -> {
+ logDebug { "USI low battery notification clicked." }
logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED)
updateSuppression(true)
if (inputDeviceId == null) return
@@ -233,6 +243,8 @@
}
companion object {
+ val TAG = StylusUsiPowerUI::class.simpleName.orEmpty()
+
// Low battery threshold matches CrOS, see:
// https://source.chromium.org/chromium/chromium/src/+/main:ash/system/power/peripheral_battery_notifier.cc;l=41
private const val LOW_BATTERY_THRESHOLD = 0.16f
@@ -251,3 +263,9 @@
@VisibleForTesting const val KEY_SETTINGS_FRAGMENT_ARGS = ":settings:show_fragment_args"
}
}
+
+private inline fun logDebug(message: () -> String) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(StylusUsiPowerUI.TAG, message())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
index e092f01..8e2b05c 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
@@ -66,7 +66,7 @@
private fun switchToManagedProfile() {
try {
applicationContext.startActivityAsUser(
- Intent(Intent.ACTION_DIAL, phoneNumber),
+ Intent(Intent.ACTION_CALL, phoneNumber),
ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(),
UserHandle.of(managedProfileUserId)
)
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
index 60241a9..cf0184f 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
@@ -27,7 +27,7 @@
* pass through to the window below.
*
* @param touchableRegionSetter a function that, given the view and an out rect, fills the rect with
- * the touchable region of this view.
+ * the touchable region of this view.
*/
class TouchableRegionViewController(
view: View,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
index 01a81de..1612388 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
@@ -35,7 +35,7 @@
* Animates [innerView] and its children into view.
*
* @return true if the animation was successfully started and false if the animation can't be
- * run for any reason.
+ * run for any reason.
*
* See [ViewHierarchyAnimator.animateAddition].
*/
@@ -55,7 +55,7 @@
* Animates [innerView] and its children out of view.
*
* @return true if the animation was successfully started and false if the animation can't be
- * run for any reason.
+ * run for any reason.
*
* See [ViewHierarchyAnimator.animateRemoval].
*/
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
index fe46318..125cc76 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
@@ -28,10 +28,10 @@
* A container for all the state needed to display a chipbar via [ChipbarCoordinator].
*
* @property startIcon the icon to display at the start of the chipbar (on the left in LTR locales;
- * on the right in RTL locales).
+ * on the right in RTL locales).
* @property text the text to display.
* @property endItem an optional end item to display at the end of the chipbar (on the right in LTR
- * locales; on the left in RTL locales).
+ * locales; on the left in RTL locales).
* @property vibrationEffect an optional vibration effect when the chipbar is displayed
* @property allowSwipeToDismiss true if users are allowed to swipe up to dismiss this chipbar.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
index 2683971..981f429 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
@@ -61,8 +61,6 @@
foldStateProvider.stop()
}
- override fun onHingeAngleUpdate(angle: Float) {}
-
override fun onFoldUpdate(@FoldUpdate update: Int) {
val now = clock.elapsedRealtime()
when (update) {
@@ -77,6 +75,10 @@
}
}
+ override fun onUnfoldedScreenAvailable() {
+ Log.d(TAG, "Unfolded screen available")
+ }
+
private fun dispatchState(@LoggedFoldedStates current: Int) {
val now = clock.elapsedRealtime()
val previous = lastState
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
index 5f89d5d..9304a46 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
@@ -45,7 +45,7 @@
*
* @param successCallback is called when the user creation is successful.
* @param errorCallback is called when userManager.createUser returns null. (Exceptions are not
- * handled by this class)
+ * handled by this class)
*/
fun createUser(
userName: String?,
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index 70523bb..a0b56aa 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -17,11 +17,8 @@
package com.android.systemui.user.data.repository
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
import android.content.Context
import android.content.pm.UserInfo
-import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
@@ -121,7 +118,6 @@
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val globalSettings: GlobalSettings,
private val tracker: UserTracker,
- private val activityManager: IActivityManager,
featureFlags: FeatureFlags,
) : UserRepository {
@@ -213,18 +209,18 @@
private fun observeUserSwitching() {
conflatedCallbackFlow {
val callback =
- object : UserSwitchObserver() {
- override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback) {
+ object : UserTracker.Callback {
+ override fun onUserChanging(newUser: Int, userContext: Context) {
trySendWithFailureLogging(true, TAG, "userSwitching started")
}
- override fun onUserSwitchComplete(newUserId: Int) {
+ override fun onUserChanged(newUserId: Int, userContext: Context) {
trySendWithFailureLogging(false, TAG, "userSwitching completed")
}
}
- activityManager.registerUserSwitchObserver(callback, TAG)
+ tracker.addCallback(callback, mainDispatcher.asExecutor())
trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
- awaitClose { activityManager.unregisterUserSwitchObserver(callback) }
+ awaitClose { tracker.removeCallback(callback) }
}
.onEach { _isUserSwitchingInProgress.value = it }
// TODO (b/262838215), Make this stateIn and initialize directly in field declaration
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
index 2f63f32..f026f0f 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
@@ -313,7 +313,7 @@
* to create a new one.
*
* @return The multi-user user ID of the newly created guest user, or [UserHandle.USER_NULL] if
- * the guest couldn't be created.
+ * the guest couldn't be created.
*/
@UserIdInt
private suspend fun createInBackground(): Int {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index 082c8cc..13b3b1a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -18,8 +18,10 @@
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
+import android.widget.ImageView
import androidx.test.filters.SmallTest
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
@@ -30,6 +32,7 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
@@ -37,6 +40,7 @@
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@SmallTest
@@ -76,7 +80,9 @@
Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
.thenReturn(passwordEntry)
`when`(keyguardPasswordView.resources).thenReturn(context.resources)
- keyguardPasswordViewController =
+ `when`(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
+ .thenReturn(mock(ImageView::class.java))
+ keyguardPasswordViewController =
KeyguardPasswordViewController(
keyguardPasswordView,
keyguardUpdateMonitor,
@@ -113,6 +119,18 @@
}
@Test
+ fun onApplyWindowInsetsListener_onApplyWindowInsets() {
+ `when`(keyguardViewController.isBouncerShowing).thenReturn(false)
+ val argumentCaptor = ArgumentCaptor.forClass(View.OnApplyWindowInsetsListener::class.java)
+
+ keyguardPasswordViewController.onViewAttached()
+ verify(keyguardPasswordView).setOnApplyWindowInsetsListener(argumentCaptor.capture())
+ argumentCaptor.value.onApplyWindowInsets(keyguardPasswordView, null)
+
+ verify(keyguardPasswordView).hideKeyboard()
+ }
+
+ @Test
fun testHideKeyboardWhenOnPause() {
keyguardPasswordViewController.onPause()
keyguardPasswordView.post {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 1bbc199..531006d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -37,6 +37,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -160,6 +161,29 @@
}
@Test
+ public void testOnApplyWindowInsets_disappearAnimation_paddingNotSet() {
+ int paddingBottom = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin);
+ int imeInsetAmount = paddingBottom + 1;
+ int systemBarInsetAmount = 0;
+ initMode(MODE_DEFAULT);
+
+ Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
+ Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
+
+ WindowInsets insets = new WindowInsets.Builder()
+ .setInsets(ime(), imeInset)
+ .setInsetsIgnoringVisibility(systemBars(), systemBarInset)
+ .build();
+
+ ensureViewFlipperIsMocked();
+ mKeyguardSecurityContainer.startDisappearAnimation(
+ KeyguardSecurityModel.SecurityMode.Password);
+ mKeyguardSecurityContainer.onApplyWindowInsets(insets);
+ assertThat(mKeyguardSecurityContainer.getPaddingBottom()).isNotEqualTo(imeInsetAmount);
+ }
+
+ @Test
public void testDefaultViewMode() {
initMode(MODE_ONE_HANDED);
initMode(MODE_DEFAULT);
@@ -376,6 +400,17 @@
assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(1);
}
+ @Test
+ public void testDisappearAnimationPassword() {
+ ensureViewFlipperIsMocked();
+ KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+ when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+
+ mKeyguardSecurityContainer
+ .startDisappearAnimation(KeyguardSecurityModel.SecurityMode.Password);
+ verify(keyguardPasswordView).setDisappearAnimationListener(any());
+ }
+
private BackEvent createBackEvent(float touchX, float progress) {
return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT);
}
@@ -446,4 +481,12 @@
mUserSwitcherController, () -> {
}, mFalsingA11yDelegate);
}
+
+ private void ensureViewFlipperIsMocked() {
+ mSecurityViewFlipper = mock(KeyguardSecurityViewFlipper.class);
+ KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+ when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+ mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
+ }
+
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index f510768..bd77c32 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -59,8 +59,6 @@
import static org.mockito.Mockito.when;
import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
@@ -98,7 +96,6 @@
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.IRemoteCallback;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -157,6 +154,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -240,8 +238,6 @@
@Mock
private KeyguardUpdateMonitorLogger mKeyguardUpdateMonitorLogger;
@Mock
- private IActivityManager mActivityService;
- @Mock
private SessionTracker mSessionTracker;
@Mock
private UiEventLogger mUiEventLogger;
@@ -283,8 +279,6 @@
@Before
public void setup() throws RemoteException {
MockitoAnnotations.initMocks(this);
- when(mActivityService.getCurrentUser()).thenReturn(mCurrentUserInfo);
- when(mActivityService.getCurrentUserId()).thenReturn(mCurrentUserId);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mAuthController.isFaceAuthEnrolled(anyInt())).thenReturn(true);
when(mFaceManager.getSensorPropertiesInternal()).thenReturn(mFaceSensorProperties);
@@ -323,13 +317,11 @@
mMockitoSession = ExtendedMockito.mockitoSession()
.spyStatic(SubscriptionManager.class)
- .spyStatic(ActivityManager.class)
.startMocking();
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.when(SubscriptionManager::getDefaultSubscriptionId);
KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId);
when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
- ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
mContext.getOrCreateTestableResources().addOverride(
com.android.systemui.R.integer.config_face_auth_supported_posture,
@@ -1082,11 +1074,6 @@
@Test
public void testBiometricsCleared_whenUserSwitches() throws Exception {
- final IRemoteCallback reply = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- } // do nothing
- };
final BiometricAuthenticated dummyAuthentication =
new BiometricAuthenticated(true /* authenticated */, true /* strong */);
mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication);
@@ -1094,18 +1081,13 @@
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1);
- mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply);
+ mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, new CountDownLatch(0));
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0);
}
@Test
public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
- final IRemoteCallback reply = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- } // do nothing
- };
mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 6333a68..3ec49b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -354,7 +354,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
@@ -362,7 +364,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
@@ -370,7 +374,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
@@ -379,7 +385,9 @@
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
@@ -388,7 +396,9 @@
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
@@ -396,7 +406,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
@@ -404,7 +416,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -412,7 +426,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -421,7 +437,9 @@
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -430,7 +448,9 @@
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
@@ -438,7 +458,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
@@ -446,7 +468,9 @@
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
@@ -454,7 +478,9 @@
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
@@ -462,7 +488,9 @@
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
@@ -480,7 +508,9 @@
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
@@ -489,7 +519,9 @@
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
@@ -498,7 +530,9 @@
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
@@ -506,7 +540,9 @@
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
@@ -524,7 +560,9 @@
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -533,7 +571,9 @@
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -542,7 +582,9 @@
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
@@ -550,7 +592,9 @@
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_0() =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index e35b2a3..28e80057 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -39,11 +39,9 @@
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import java.io.File
-import java.util.Optional
-import java.util.function.Consumer
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -58,7 +56,9 @@
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
@@ -66,9 +66,10 @@
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.clearInvocations
import org.mockito.MockitoAnnotations
+import java.io.File
+import java.util.*
+import java.util.function.Consumer
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -146,6 +147,7 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
+ whenever(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf())
`when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
delayableExecutor = FakeExecutor(FakeSystemClock())
@@ -945,6 +947,28 @@
controller.bindComponentForPanel(TEST_COMPONENT)
verify(bindingController).bindServiceForPanel(TEST_COMPONENT)
}
+
+ @Test
+ fun testRemoveFavoriteRemovesFavorite() {
+ val componentName = ComponentName(context, "test.Cls")
+ controller.addFavorite(
+ componentName,
+ "test structure",
+ ControlInfo(
+ controlId = "testId",
+ controlTitle = "Test Control",
+ controlSubtitle = "test control subtitle",
+ deviceType = DeviceTypes.TYPE_LIGHT,
+ ),
+ )
+
+ controller.removeFavorites(componentName)
+ delayableExecutor.runAllReady()
+
+ verify(authorizedPanelsRepository)
+ .removeAuthorizedPanels(eq(setOf(componentName.packageName)))
+ assertThat(controller.getFavorites()).isEmpty()
+ }
}
private class DidRunRunnable() : Runnable {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
index b91a3fd..7ac1953 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
@@ -115,6 +115,18 @@
assertThat(sharedPrefs.getStringSet(KEY, null)).containsExactly(TEST_PACKAGE)
}
+ @Test
+ fun testRemoveAuthorizedPackageRemovesIt() {
+ val sharedPrefs = FakeSharedPreferences()
+ val fileManager = FakeUserFileManager(mapOf(0 to sharedPrefs))
+ val repository = createRepository(fileManager)
+ repository.addAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ repository.removeAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ assertThat(sharedPrefs.getStringSet(KEY, null)).isEmpty()
+ }
+
private fun createRepository(userFileManager: UserFileManager): AuthorizedPanelsRepositoryImpl {
return AuthorizedPanelsRepositoryImpl(mContext, userFileManager, userTracker)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
index 0c9986d..5a613aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
@@ -104,7 +104,9 @@
controlsSettingsRepository,
userTracker,
activityStarter
- ) { context, _ -> TestableAlertDialog(context).also { dialog = it } }
+ ) { context, _ ->
+ TestableAlertDialog(context).also { dialog = it }
+ }
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
new file mode 100644
index 0000000..1e8cd41
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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.controls.ui
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.FakeSystemUIDialogController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ControlsDialogsFactoryTest : SysuiTestCase() {
+
+ private companion object {
+ const val APP_NAME = "Test App"
+ }
+
+ private val fakeDialogController = FakeSystemUIDialogController()
+
+ private lateinit var underTest: ControlsDialogsFactory
+
+ @Before
+ fun setup() {
+ underTest = ControlsDialogsFactory { fakeDialogController.dialog }
+ }
+
+ @Test
+ fun testCreatesRemoveAppDialog() {
+ val dialog = underTest.createRemoveAppDialog(context, APP_NAME) {}
+
+ verify(dialog)
+ .setTitle(
+ eq(context.getString(R.string.controls_panel_remove_app_authorization, APP_NAME))
+ )
+ verify(dialog).setCanceledOnTouchOutside(eq(true))
+ }
+
+ @Test
+ fun testPositiveClickRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.clickPositive()
+
+ assertThat(dialogResult).isTrue()
+ }
+
+ @Test
+ fun testNeutralClickRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.clickNeutral()
+
+ assertThat(dialogResult).isFalse()
+ }
+
+ @Test
+ fun testCancelRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.cancel()
+
+ assertThat(dialogResult).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index aa90e2a..23faa99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -52,6 +52,7 @@
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.FakeSystemUIDialogController
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -63,21 +64,20 @@
import com.android.wm.shell.TaskView
import com.android.wm.shell.TaskViewFactory
import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
-import java.util.Optional
-import java.util.function.Consumer
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.anyString
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
+import java.util.Optional
+import java.util.function.Consumer
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -98,13 +98,15 @@
@Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
@Mock lateinit var featureFlags: FeatureFlags
@Mock lateinit var packageManager: PackageManager
- val sharedPreferences = FakeSharedPreferences()
- lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
- var uiExecutor = FakeExecutor(FakeSystemClock())
- var bgExecutor = FakeExecutor(FakeSystemClock())
- lateinit var underTest: ControlsUiControllerImpl
- lateinit var parent: FrameLayout
+ private val sharedPreferences = FakeSharedPreferences()
+ private val fakeDialogController = FakeSystemUIDialogController()
+ private val uiExecutor = FakeExecutor(FakeSystemClock())
+ private val bgExecutor = FakeExecutor(FakeSystemClock())
+
+ private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
+ private lateinit var parent: FrameLayout
+ private lateinit var underTest: ControlsUiControllerImpl
@Before
fun setup() {
@@ -125,12 +127,12 @@
underTest =
ControlsUiControllerImpl(
- Lazy { controlsController },
+ { controlsController },
context,
packageManager,
uiExecutor,
bgExecutor,
- Lazy { controlsListingController },
+ { controlsListingController },
controlActionCoordinator,
activityStarter,
iconCache,
@@ -142,7 +144,8 @@
controlsSettingsRepository,
authorizedPanelsRepository,
featureFlags,
- dumpManager
+ ControlsDialogsFactory { fakeDialogController.dialog },
+ dumpManager,
)
`when`(
userFileManager.getSharedPreferences(
@@ -410,8 +413,45 @@
verify(controlsListingController, never()).removeCallback(any())
}
+ @Test
+ fun testRemovingAppsRemovesFavorite() {
+ val componentName = ComponentName(context, "cls")
+ whenever(controlsController.removeFavorites(eq(componentName))).thenReturn(true)
+ val panel = SelectedItem.PanelItem("App name", componentName)
+ sharedPreferences
+ .edit()
+ .putString("controls_component", panel.componentName.flattenToString())
+ .putString("controls_structure", panel.appName.toString())
+ .putBoolean("controls_is_panel", true)
+ .commit()
+ underTest.show(parent, {}, context)
+ underTest.startRemovingApp(componentName, "Test App")
+
+ fakeDialogController.clickPositive()
+
+ verify(controlsController).removeFavorites(eq(componentName))
+ assertThat(underTest.getPreferredSelectedItem(emptyList()))
+ .isEqualTo(SelectedItem.EMPTY_SELECTION)
+ with(sharedPreferences) {
+ assertThat(contains("controls_component")).isFalse()
+ assertThat(contains("controls_structure")).isFalse()
+ assertThat(contains("controls_is_panel")).isFalse()
+ }
+ }
+
+ @Test
+ fun testHideCancelsTheRemoveAppDialog() {
+ val componentName = ComponentName(context, "cls")
+ underTest.show(parent, {}, context)
+ underTest.startRemovingApp(componentName, "Test App")
+
+ underTest.hide(parent)
+
+ verify(fakeDialogController.dialog).cancel()
+ }
+
private fun setUpPanel(panel: SelectedItem.PanelItem): ControlsServiceInfo {
- val activity = ComponentName("pkg", "activity")
+ val activity = ComponentName(context, "activity")
sharedPreferences
.edit()
.putString("controls_component", panel.componentName.flattenToString())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
index dbaf94f..483ab3b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
@@ -37,7 +37,9 @@
context,
layoutId = 0,
labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
- ) { true }
+ ) {
+ true
+ }
ids.forEachIndexed { index, id -> assertThat(adapter.getItemId(index)).isEqualTo(id) }
}
@@ -51,7 +53,9 @@
context,
layoutId = 0,
labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
- ) { position -> position == 0 }
+ ) { position ->
+ position == 0
+ }
assertThat(adapter.isEnabled(0)).isTrue()
assertThat(adapter.isEnabled(1)).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 9e70c27..aa17d49 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -73,6 +73,7 @@
private static final ComponentName LOW_LIGHT_COMPONENT = new ComponentName("package",
"lowlight");
private static final String DREAM_COMPONENT = "package/dream";
+ private static final String WINDOW_NAME = "test";
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -190,7 +191,8 @@
mUiEventLogger,
mTouchInsetManager,
LOW_LIGHT_COMPONENT,
- mDreamOverlayCallbackController);
+ mDreamOverlayCallbackController,
+ WINDOW_NAME);
}
public IDreamOverlayClient getClient() throws RemoteException {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index ef62abf..175da0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -33,6 +33,8 @@
import com.android.systemui.condition.SelfExecutingMonitor;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.shared.condition.Monitor;
@@ -65,6 +67,9 @@
@Mock
private View mBcSmartspaceView;
+ @Mock
+ private FeatureFlags mFeatureFlags;
+
private Monitor mMonitor;
private final Set<Condition> mPreconditions = new HashSet<>();
@@ -73,6 +78,8 @@
public void setup() {
MockitoAnnotations.initMocks(this);
mMonitor = SelfExecutingMonitor.createInstance();
+
+ when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(false);
}
/**
@@ -85,12 +92,22 @@
verify(mDreamOverlayStateController, never()).addComplication(eq(mComplication));
}
- private SmartSpaceComplication.Registrant getRegistrant() {
- return new SmartSpaceComplication.Registrant(
- mDreamOverlayStateController,
- mComplication,
- mSmartspaceController,
- mMonitor);
+ @Test
+ public void testRegistrantStart_featureEnabled_addOverlayStateCallback() {
+ final SmartSpaceComplication.Registrant registrant = getRegistrant();
+ registrant.start();
+
+ verify(mDreamOverlayStateController).addCallback(any());
+ }
+
+ @Test
+ public void testRegistrantStart_featureDisabled_doesNotAddOverlayStateCallback() {
+ when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(true);
+
+ final SmartSpaceComplication.Registrant registrant = getRegistrant();
+ registrant.start();
+
+ verify(mDreamOverlayStateController, never()).addCallback(any());
}
@Test
@@ -188,4 +205,13 @@
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mBcSmartspaceView);
assertEquals(viewHolder.getView(), viewHolder.getView());
}
+
+ private SmartSpaceComplication.Registrant getRegistrant() {
+ return new SmartSpaceComplication.Registrant(
+ mDreamOverlayStateController,
+ mComplication,
+ mSmartspaceController,
+ mMonitor,
+ mFeatureFlags);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index 21ad5e2..5dc04f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -30,6 +30,7 @@
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
@@ -38,11 +39,14 @@
import com.android.systemui.keyguard.data.repository.BiometricType.REAR_FINGERPRINT
import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT
import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -62,6 +66,7 @@
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner::class)
@@ -78,6 +83,7 @@
private lateinit var biometricManagerCallback:
ArgumentCaptor<IBiometricEnabledOnKeyguardCallback.Stub>
private lateinit var userRepository: FakeUserRepository
+ private lateinit var devicePostureRepository: FakeDevicePostureRepository
private lateinit var testDispatcher: TestDispatcher
private lateinit var testScope: TestScope
@@ -90,6 +96,7 @@
testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher)
userRepository = FakeUserRepository()
+ devicePostureRepository = FakeDevicePostureRepository()
}
private suspend fun createBiometricSettingsRepository() {
@@ -108,6 +115,7 @@
looper = testableLooper!!.looper,
dumpManager = dumpManager,
biometricManager = biometricManager,
+ devicePostureRepository = devicePostureRepository,
)
testScope.runCurrent()
}
@@ -299,6 +307,50 @@
verify(biometricManager, times(1)).registerEnabledOnKeyguardCallback(any())
}
+ @Test
+ fun faceAuthIsAlwaysSupportedIfSpecificPostureIsNotConfigured() =
+ testScope.runTest {
+ overrideResource(
+ R.integer.config_face_auth_supported_posture,
+ DevicePostureController.DEVICE_POSTURE_UNKNOWN
+ )
+
+ createBiometricSettingsRepository()
+
+ assertThat(collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)()).isTrue()
+ }
+
+ @Test
+ fun faceAuthIsSupportedOnlyWhenDevicePostureMatchesConfigValue() =
+ testScope.runTest {
+ overrideResource(
+ R.integer.config_face_auth_supported_posture,
+ DevicePostureController.DEVICE_POSTURE_FLIPPED
+ )
+
+ createBiometricSettingsRepository()
+
+ val isFaceAuthSupported =
+ collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)
+
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.CLOSED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.HALF_OPENED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.OPENED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.UNKNOWN)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.FLIPPED)
+ assertThat(isFaceAuthSupported()).isTrue()
+ }
+
private fun enrollmentChange(biometricType: BiometricType, userId: Int, enabled: Boolean) {
authControllerCallback.value.onEnrollmentsChanged(biometricType, userId, enabled)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
new file mode 100644
index 0000000..bd6b7a8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.keyguard.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePostureRepositoryTest : SysuiTestCase() {
+ private lateinit var underTest: DevicePostureRepository
+ private lateinit var testScope: TestScope
+ @Mock private lateinit var devicePostureController: DevicePostureController
+ @Captor private lateinit var callback: ArgumentCaptor<DevicePostureController.Callback>
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ testScope = TestScope()
+ underTest = DevicePostureRepositoryImpl(postureController = devicePostureController)
+ }
+
+ @Test
+ fun postureChangesArePropagated() =
+ testScope.runTest {
+ whenever(devicePostureController.devicePosture)
+ .thenReturn(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+ val currentPosture = collectLastValue(underTest.currentDevicePosture)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+
+ verify(devicePostureController).addCallback(callback.capture())
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_UNKNOWN)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.UNKNOWN)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_CLOSED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.CLOSED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_HALF_OPENED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.HALF_OPENED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_OPENED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.OPENED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index d2db910..f9493d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -62,7 +62,9 @@
fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// We got a source but still have no sensor locations, so should be sticking with
// the default effect.
@@ -71,14 +73,18 @@
)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// We got a location for the face sensor, but we unlocked with fingerprint.
val faceLocation = Point(250, 0)
fakeKeyguardRepository.setFaceSensorLocation(faceLocation)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// Now we have fingerprint sensor locations, and wake and unlock via fingerprint.
val fingerprintLocation = Point(500, 500)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 8bd8be5..c727b3a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -308,7 +308,7 @@
TestConfig(
isVisible = true,
isClickable = false,
- isActivated = true,
+ isActivated = false,
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
@@ -363,7 +363,7 @@
TestConfig(
isVisible = true,
isClickable = false,
- isActivated = true,
+ isActivated = false,
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index 8c54da1..ab0669a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -139,6 +139,7 @@
@Mock private lateinit var logger: MediaUiEventLogger
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
+ lateinit var remoteCastNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
private val clock = FakeSystemClock()
@Mock private lateinit var tunerService: TunerService
@@ -207,6 +208,20 @@
}
build()
}
+ remoteCastNotification =
+ SbnBuilder().run {
+ setPkg(SYSTEM_PACKAGE_NAME)
+ modifyNotification(context).also {
+ it.setSmallIcon(android.R.drawable.ic_media_pause)
+ it.setStyle(
+ MediaStyle().apply {
+ setMediaSession(session.sessionToken)
+ setRemotePlaybackInfo("Remote device", 0, null)
+ }
+ )
+ }
+ build()
+ }
metadataBuilder =
MediaMetadata.Builder().apply {
putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
@@ -247,6 +262,7 @@
whenever(mediaFlags.isExplicitIndicatorEnabled()).thenReturn(true)
whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(false)
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
}
@@ -400,33 +416,8 @@
@Test
fun testOnNotificationAdded_isRcn_markedRemote() {
- val rcn =
- SbnBuilder().run {
- setPkg(SYSTEM_PACKAGE_NAME)
- modifyNotification(context).also {
- it.setSmallIcon(android.R.drawable.ic_media_pause)
- it.setStyle(
- MediaStyle().apply {
- setMediaSession(session.sessionToken)
- setRemotePlaybackInfo("Remote device", 0, null)
- }
- )
- }
- build()
- }
+ addNotificationAndLoad(remoteCastNotification)
- mediaDataManager.onNotificationAdded(KEY, rcn)
- assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
- assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
- verify(listener)
- .onMediaDataLoaded(
- eq(KEY),
- eq(null),
- capture(mediaDataCaptor),
- eq(true),
- eq(0),
- eq(false)
- )
assertThat(mediaDataCaptor.value!!.playbackLocation)
.isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
verify(logger)
@@ -710,6 +701,56 @@
}
@Test
+ fun testOnNotificationRemoved_withResumption_isRemoteAndRemoteAllowed() {
+ // With the flag enabled to allow remote media to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // GIVEN that the manager has a notification with a resume action, but is not local
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
+ whenever(playbackInfo.playbackType)
+ .thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+ addNotificationAndLoad()
+ val data = mediaDataCaptor.value
+ val dataRemoteWithResume =
+ data.copy(resumeAction = Runnable {}, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+ mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+ // WHEN the notification is removed
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN the media data is converted to a resume state
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value.resumption).isTrue()
+ }
+
+ @Test
+ fun testOnNotificationRemoved_withResumption_isRcnAndRemoteAllowed() {
+ // With the flag enabled to allow remote media to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // GIVEN that the manager has a remote cast notification
+ addNotificationAndLoad(remoteCastNotification)
+ val data = mediaDataCaptor.value
+ assertThat(data.playbackLocation).isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
+ val dataRemoteWithResume = data.copy(resumeAction = Runnable {})
+ mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+ // WHEN the RCN is removed
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN the media data is removed
+ verify(listener).onMediaDataRemoved(eq(KEY))
+ }
+
+ @Test
fun testOnNotificationRemoved_withResumption_tooManyPlayers() {
// Given the maximum number of resume controls already
val desc =
@@ -1654,22 +1695,7 @@
)
// update to remote cast
- val rcn =
- SbnBuilder().run {
- setPkg(SYSTEM_PACKAGE_NAME) // System package
- modifyNotification(context).also {
- it.setSmallIcon(android.R.drawable.ic_media_pause)
- it.setStyle(
- MediaStyle().apply {
- setMediaSession(session.sessionToken)
- setRemotePlaybackInfo("Remote device", 0, null)
- }
- )
- }
- build()
- }
-
- mediaDataManager.onNotificationAdded(KEY, rcn)
+ mediaDataManager.onNotificationAdded(KEY, remoteCastNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(logger)
@@ -2038,9 +2064,14 @@
verify(listener).onMediaDataRemoved(eq(KEY))
}
- /** Helper function to add a media notification and capture the resulting MediaData */
+ /** Helper function to add a basic media notification and capture the resulting MediaData */
private fun addNotificationAndLoad() {
- mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ addNotificationAndLoad(mediaNotification)
+ }
+
+ /** Helper function to add the given notification and capture the resulting MediaData */
+ private fun addNotificationAndLoad(sbn: StatusBarNotification) {
+ mediaDataManager.onNotificationAdded(KEY, sbn)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(listener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
index 136ace1..4dfa626 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
@@ -38,6 +38,7 @@
import com.android.systemui.media.controls.models.player.MediaDeviceData
import com.android.systemui.media.controls.pipeline.MediaDataManager
import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.settings.UserTracker
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
@@ -92,6 +93,7 @@
@Mock private lateinit var mockContext: Context
@Mock private lateinit var pendingIntent: PendingIntent
@Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var mediaFlags: MediaFlags
@Captor lateinit var callbackCaptor: ArgumentCaptor<ResumeMediaBrowser.Callback>
@Captor lateinit var actionCaptor: ArgumentCaptor<Runnable>
@@ -134,6 +136,7 @@
whenever(mockContext.packageManager).thenReturn(context.packageManager)
whenever(mockContext.contentResolver).thenReturn(context.contentResolver)
whenever(mockContext.userId).thenReturn(context.userId)
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
executor = FakeExecutor(clock)
resumeListener =
@@ -146,7 +149,8 @@
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -188,7 +192,8 @@
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
listener.setManager(mediaDataManager)
verify(broadcastDispatcher, never())
@@ -244,6 +249,32 @@
}
@Test
+ fun testOnLoad_localCast_remoteResumeAllowed_doesCheck() {
+ // If local cast media is allowed to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // When media data is loaded that has not been checked yet, and is a local cast
+ val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+ resumeListener.onMediaDataLoaded(KEY, null, dataCast)
+
+ // Then we report back to the manager
+ verify(mediaDataManager).setResumeAction(KEY, null)
+ }
+
+ @Test
+ fun testOnLoad_remoteCast_remoteResumeAllowed_doesCheck() {
+ // If local cast media is allowed to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // When media data is loaded that has not been checked yet, and is a remote cast
+ val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
+ resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
+
+ // Then we do not take action
+ verify(mediaDataManager, never()).setResumeAction(any(), any())
+ }
+
+ @Test
fun testOnLoad_checksForResume_hasService() {
setUpMbsWithValidResolveInfo()
@@ -389,7 +420,8 @@
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -421,7 +453,8 @@
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -463,7 +496,8 @@
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
index 4fc9ca7..85e8d07 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
@@ -70,8 +70,7 @@
context,
appPackageName = null,
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -86,8 +85,7 @@
context,
appPackageName = null,
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -119,8 +117,7 @@
context,
appPackageName = "fakePackageName",
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -135,8 +132,7 @@
context,
appPackageName = "fakePackageName",
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -154,7 +150,9 @@
context,
appPackageName = "fakePackageName",
isReceiver = false
- ) { exceptionTriggered = true }
+ ) {
+ exceptionTriggered = true
+ }
assertThat(exceptionTriggered).isTrue()
}
@@ -167,7 +165,9 @@
context,
appPackageName = "fakePackageName",
isReceiver = true
- ) { exceptionTriggered = true }
+ ) {
+ exceptionTriggered = true
+ }
assertThat(exceptionTriggered).isTrue()
}
@@ -179,8 +179,7 @@
context,
PACKAGE_NAME,
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isTrue()
assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
@@ -194,8 +193,7 @@
context,
PACKAGE_NAME,
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isTrue()
assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
index 41ac3213..d364f47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
@@ -18,13 +18,21 @@
import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+import static org.junit.Assert.assertTrue;
+
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.contrast.Contrast;
import com.android.systemui.monet.dynamiccolor.DynamicColor;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
import com.android.systemui.monet.dynamiccolor.ToneDeltaConstraint;
import com.android.systemui.monet.dynamiccolor.TonePolarity;
import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.DynamicScheme;
+import com.android.systemui.monet.scheme.SchemeContent;
+import com.android.systemui.monet.scheme.SchemeFidelity;
+import com.android.systemui.monet.scheme.SchemeMonochrome;
import com.android.systemui.monet.scheme.SchemeTonalSpot;
import org.junit.Test;
@@ -90,4 +98,92 @@
final SchemeTonalSpot darkScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), true, 0.0);
assertThat(dynamicColor.getArgb(darkScheme)).isSameColorAs(0x33ffffff);
}
+
+ @Test
+ public void respectsContrast() {
+ final Hct[] seedColors =
+ new Hct[]{
+ Hct.fromInt(0xFFFF0000),
+ Hct.fromInt(0xFFFFFF00),
+ Hct.fromInt(0xFF00FF00),
+ Hct.fromInt(0xFF0000FF)
+ };
+
+ final double[] contrastLevels = {-1.0, -0.5, 0.0, 0.5, 1.0};
+
+ for (Hct seedColor : seedColors) {
+ for (double contrastLevel : contrastLevels) {
+ for (boolean isDark : new boolean[]{false, true}) {
+ final DynamicScheme[] schemes =
+ new DynamicScheme[]{
+ new SchemeContent(seedColor, isDark, contrastLevel),
+ new SchemeMonochrome(seedColor, isDark, contrastLevel),
+ new SchemeTonalSpot(seedColor, isDark, contrastLevel),
+ new SchemeFidelity(seedColor, isDark, contrastLevel)
+ };
+ for (final DynamicScheme scheme : schemes) {
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onPrimary,
+ MaterialDynamicColors.primary));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onPrimaryContainer,
+ MaterialDynamicColors.primaryContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onSecondary,
+ MaterialDynamicColors.secondary));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onSecondaryContainer,
+ MaterialDynamicColors.secondaryContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onTertiary,
+ MaterialDynamicColors.tertiary));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onTertiaryContainer,
+ MaterialDynamicColors.tertiaryContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onError,
+ MaterialDynamicColors.error));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onErrorContainer,
+ MaterialDynamicColors.errorContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onBackground,
+ MaterialDynamicColors.background));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onSurfaceVariant,
+ MaterialDynamicColors.surfaceVariant));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onSurfaceInverse,
+ MaterialDynamicColors.surfaceInverse));
+ }
+ }
+ }
+ }
+ }
+
+ private boolean pairSatisfiesContrast(DynamicScheme scheme, DynamicColor fg, DynamicColor bg) {
+ double fgTone = fg.getHct(scheme).getTone();
+ double bgTone = bg.getHct(scheme).getTone();
+ // TODO(b/270915664) - Fix inconsistencies.
+ // TODO(b/270915664) - Minimum requirement should be 4.5 when not reducing contrast.
+ double minimumRequirement = 3.0;
+ return Contrast.ratioOfTones(fgTone, bgTone) >= minimumRequirement;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index b872389..376b7cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -25,7 +25,6 @@
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskController.Companion.INTENT_EXTRA_USE_STYLUS_MODE
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.any
@@ -228,10 +227,10 @@
val intentCaptor = argumentCaptor<Intent>()
verify(context).startActivity(capture(intentCaptor))
intentCaptor.value.let { intent ->
- assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
verify(eventLogger).logNoteTaskOpened(expectedInfo)
verifyZeroInteractions(bubbles)
@@ -258,10 +257,10 @@
val intentCaptor = argumentCaptor<Intent>()
verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
intentCaptor.value.let { intent ->
- assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
verifyZeroInteractions(eventLogger)
}
@@ -286,10 +285,10 @@
val intentCaptor = argumentCaptor<Intent>()
verify(context).startActivity(capture(intentCaptor))
intentCaptor.value.let { intent ->
- assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
verify(eventLogger).logNoteTaskOpened(expectedInfo)
verifyZeroInteractions(bubbles)
@@ -462,7 +461,7 @@
assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
}
@@ -489,7 +488,7 @@
assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
}
// endregion
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
index d6495d8..7f64f8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
@@ -57,8 +57,9 @@
fun resolveInfo_shouldReturnInfo() {
val packageName = "com.android.note.app"
val uid = 123456
- whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
- .then { listOf(packageName) }
+ whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+ listOf(packageName)
+ }
whenever(
packageManager.getApplicationInfoAsUser(
eq(packageName),
@@ -78,8 +79,9 @@
@Test
fun resolveInfo_packageManagerThrowsException_shouldReturnInfoWithZeroUid() {
val packageName = "com.android.note.app"
- whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
- .then { listOf(packageName) }
+ whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+ listOf(packageName)
+ }
whenever(
packageManager.getApplicationInfoAsUser(
eq(packageName),
@@ -98,8 +100,9 @@
@Test
fun resolveInfo_noRoleHolderIsSet_shouldReturnNull() {
- whenever(roleManager.getRoleHoldersAsUser(eq(NoteTaskInfoResolver.ROLE_NOTES), any()))
- .then { listOf<String>() }
+ whenever(roleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_NOTES), any())).then {
+ emptyList<String>()
+ }
val actual = underTest.resolveInfo()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
index a8eab50..46e0278 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
@@ -103,9 +103,7 @@
// region handleSystemKey
@Test
fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
- createNoteTaskInitializer()
- .callbacks
- .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
+ createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL)
verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.TAIL_BUTTON)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
@@ -5,4 +5,6 @@
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
index 030c59f..5e0190b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
@@ -38,6 +38,7 @@
import com.android.systemui.util.settings.GlobalSettings
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -94,6 +95,12 @@
mUserTracker)
}
+ @After
+ fun tearDown() {
+ mTile.destroy()
+ mTestableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDisabled_showsOffState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
index b4a66297..f1e3e8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
@@ -21,6 +21,7 @@
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -88,6 +89,12 @@
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testAvailable() {
assertThat(tile.isAvailable).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index 95e7ad9f..a5c0004 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -37,6 +37,7 @@
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -103,6 +104,12 @@
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testSettingWithCorrectUser() {
assertEquals(USER, tile.mSetting.currentUser)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
index bf172f1..75fd000 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
@@ -22,6 +22,7 @@
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.BluetoothController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -79,6 +80,12 @@
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testRestrictionChecked() {
tile.refreshState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
index cfbb82f..4193854 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -90,6 +91,12 @@
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenCameraAccessEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index 18f891c..64fd09d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -53,6 +53,7 @@
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -141,6 +142,12 @@
mHotspotCallback = hotspotCallbackArgumentCaptor.getValue();
}
+ @After
+ public void tearDown() {
+ mCastTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
// -------------------------------------------------
// All these tests for enabled/disabled wifi have hotspot not enabled
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
index fdb63ca..13c30e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -101,6 +102,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void longClick_expectedAction() {
final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
index 60c1a33..ff27e02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
@@ -46,6 +46,7 @@
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -106,6 +107,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void longClick_expectedAction() {
final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
index ce62f2d..b048643 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
@@ -34,6 +34,7 @@
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.DataSaverController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -84,6 +85,12 @@
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDataSaverEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index e0b3125..b51c378 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -67,6 +67,7 @@
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import java.util.Optional
+import org.junit.After
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -129,6 +130,12 @@
tile = createTile()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
private fun setupControlsComponent() {
`when`(controlsComponent.getControlsController()).thenAnswer {
if (featureEnabled) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index ce5edb1..6c0904e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -136,7 +136,8 @@
@After
fun tearDown() {
- tile.handleSetListening(false)
+ tile.destroy()
+ testableLooper.processAllMessages()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
index 71d8aa4..7d41aa6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
@@ -54,6 +54,7 @@
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -112,6 +113,12 @@
mTile.initialize();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNotAvailable() throws RemoteException {
// Should not be available if screensaver is disabled
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
index c7aba1a..692a644 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
@@ -18,6 +18,7 @@
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.FlashlightController
import com.google.common.truth.Truth
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -71,6 +72,12 @@
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenFlashlightEnabled_isOnState() {
Mockito.`when`(flashlightController.isAvailable).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
index 9d62cfd..bd99cd4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
@@ -38,6 +38,7 @@
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -89,6 +90,12 @@
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ fontScalingTile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun isAvailable_whenFlagIsFalse_returnsFalse() {
featureFlags.set(Flags.ENABLE_FONT_SCALING_TILE, false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
index 4a2ac96..959e750 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -94,6 +95,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void handleUpdateState_wifiTetheringIsAllowed_stateIsNotUnavailable() {
MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
index abd9094..adfd7f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.WifiIndicators;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void setConnectivityStatus_defaultNetworkNotExists_updateTile() {
mTile.mSignalCallback.setConnectivityStatus(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
index 08d10fd..33921c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -88,6 +89,12 @@
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDisabled_isOffState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
index 1ab601c..e2f64b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -90,6 +91,12 @@
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenMicrophoneAccessEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
index 9638a45..c7dae83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
@@ -39,6 +39,7 @@
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -97,6 +98,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mNfcTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testIsAvailable_stockWithoutNfc_returnsFalse() {
when(mMockContext.getString(R.string.quick_settings_tiles_stock)).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
index 188c3a3..04af69c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
@@ -37,6 +37,7 @@
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -49,32 +50,23 @@
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
class NightDisplayTileTest : SysuiTestCase() {
- @Mock
- private lateinit var mHost: QSHost
+ @Mock private lateinit var mHost: QSHost
- @Mock
- private lateinit var mMetricsLogger: MetricsLogger
+ @Mock private lateinit var mMetricsLogger: MetricsLogger
- @Mock
- private lateinit var mStatusBarStateController: StatusBarStateController
+ @Mock private lateinit var mStatusBarStateController: StatusBarStateController
- @Mock
- private lateinit var mActivityStarter: ActivityStarter
+ @Mock private lateinit var mActivityStarter: ActivityStarter
- @Mock
- private lateinit var mQsLogger: QSLogger
+ @Mock private lateinit var mQsLogger: QSLogger
- @Mock
- private lateinit var mLocationController: LocationController
+ @Mock private lateinit var mLocationController: LocationController
- @Mock
- private lateinit var mColorDisplayManager: ColorDisplayManager
+ @Mock private lateinit var mColorDisplayManager: ColorDisplayManager
- @Mock
- private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
+ @Mock private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
- @Mock
- private lateinit var mNightDisplayListener: NightDisplayListener
+ @Mock private lateinit var mNightDisplayListener: NightDisplayListener
private lateinit var mTestableLooper: TestableLooper
private lateinit var mTile: NightDisplayTile
@@ -88,24 +80,30 @@
whenever(mHost.context).thenReturn(mContext)
whenever(mHost.uiEventLogger).thenReturn(mUiEventLogger)
whenever(mHost.userContext).thenReturn(mContext)
- whenever(mNightDisplayListenerBuilder.setUser(anyInt())).thenReturn(
- mNightDisplayListenerBuilder
- )
+ whenever(mNightDisplayListenerBuilder.setUser(anyInt()))
+ .thenReturn(mNightDisplayListenerBuilder)
whenever(mNightDisplayListenerBuilder.build()).thenReturn(mNightDisplayListener)
- mTile = NightDisplayTile(
- mHost,
- mTestableLooper.looper,
- Handler(mTestableLooper.looper),
- FalsingManagerFake(),
- mMetricsLogger,
- mStatusBarStateController,
- mActivityStarter,
- mQsLogger,
- mLocationController,
- mColorDisplayManager,
- mNightDisplayListenerBuilder
- )
+ mTile =
+ NightDisplayTile(
+ mHost,
+ mTestableLooper.looper,
+ Handler(mTestableLooper.looper),
+ FalsingManagerFake(),
+ mMetricsLogger,
+ mStatusBarStateController,
+ mActivityStarter,
+ mQsLogger,
+ mLocationController,
+ mColorDisplayManager,
+ mNightDisplayListenerBuilder
+ )
+ }
+
+ @After
+ fun tearDown() {
+ mTile.destroy()
+ mTestableLooper.processAllMessages()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
index 3344a17..652c138 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
@@ -37,6 +37,7 @@
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
mTile.initialize();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testIsAvailable_unsupportOneHandedProperty_shouldReturnsFalse() {
when(mTile.isSupportOneHandedMode()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
index 24287ea..3125d45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNewTile() {
assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 4722c8d..596df78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -73,6 +73,7 @@
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -161,6 +162,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNewTile() {
assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 99e5564..7913628 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -44,8 +44,8 @@
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
+import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -54,7 +54,6 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
-@Ignore("b/269171747")
public class ReduceBrightColorsTileTest extends SysuiTestCase {
@Mock
private QSHost mHost;
@@ -99,6 +98,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNotActive() {
when(mReduceBrightColorsController.isReduceBrightColorsActivated()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
index c7eb2f1..5b94cfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
@@ -48,6 +48,7 @@
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -139,6 +140,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mLockTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testSecondaryString_cameraRotateOn_returnsFaceBased() {
assertEquals(mContext.getString(R.string.rotation_lock_camera_rotation_on),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 21acc08..5aef758 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -50,6 +50,7 @@
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -114,6 +115,12 @@
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
// Test that the tile is inactive and labeled correctly when the controller is neither starting
// or recording, and that clicking on the tile in this state brings up the record prompt
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
index 3d9f650..b556571 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
@@ -39,6 +39,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -98,6 +99,12 @@
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenNightModeOn_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 52b0b6a..4f469f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -551,6 +551,7 @@
mNotificationStackSizeCalculator,
mUnlockedScreenOffAnimationController,
mShadeTransitionController,
+ mInteractionJankMonitor,
systemClock,
mKeyguardBottomAreaViewModel,
mKeyguardBottomAreaInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
index 7a74b12..56fc0c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
@@ -36,21 +36,26 @@
private val progressProvider = TestUnfoldTransitionProvider()
- @Mock private lateinit var parent: ViewGroup
+ @Mock
+ private lateinit var parent: ViewGroup
+
+ @Mock
+ private lateinit var shouldBeAnimated: () -> Boolean
private lateinit var animator: UnfoldConstantTranslateAnimator
- private val viewsIdToRegister =
- setOf(
- ViewIdToTranslate(START_VIEW_ID, Direction.START),
- ViewIdToTranslate(END_VIEW_ID, Direction.END))
+ private val viewsIdToRegister
+ get() =
+ setOf(
+ ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated),
+ ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated)
+ )
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
-
- animator =
- UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
+ whenever(shouldBeAnimated.invoke()).thenReturn(true)
+ animator = UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
animator.init(parent, MAX_TRANSLATION)
}
@@ -96,6 +101,20 @@
moveAndValidate(listOf(leftView to START, rightView to END), View.LAYOUT_DIRECTION_LTR)
}
+ @Test
+ fun onTransition_completeStartedTranslation() {
+ // GIVEN
+ val leftView = View(context)
+ whenever(parent.findViewById<View>(START_VIEW_ID)).thenReturn(leftView)
+ // To start animation, shouldBeAnimated should return true.
+ // There is a possibility for shouldBeAnimated to return false during the animation.
+ whenever(shouldBeAnimated.invoke()).thenReturn(true).thenReturn(false)
+
+ // shouldBeAnimated state may change during the animation.
+ // However, started animation should be completed.
+ moveAndValidate(listOf(leftView to START), View.LAYOUT_DIRECTION_LTR)
+ }
+
private fun moveAndValidate(list: List<Pair<View, Int>>, layoutDirection: Int) {
// Compare values as ints because -0f != 0f
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 26eff61..1fdb364 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -35,7 +35,6 @@
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
-import org.json.JSONException
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -271,10 +270,14 @@
@Test
fun jsonDeserialization_gotExpectedObject() {
- val expected = ClockSettings("ID", null).apply { _applied_timestamp = 500 }
+ val expected = ClockSettings("ID", null).apply {
+ metadata.put("appliedTimestamp", 500)
+ }
val actual = ClockSettings.deserialize("""{
"clockId":"ID",
- "_applied_timestamp":500
+ "metadata": {
+ "appliedTimestamp":500
+ }
}""")
assertEquals(expected, actual)
}
@@ -291,29 +294,32 @@
val expected = ClockSettings("ID", null)
val actual = ClockSettings.deserialize("""{
"clockId":"ID",
- "_applied_timestamp":null
+ "metadata":null
}""")
assertEquals(expected, actual)
}
- @Test(expected = JSONException::class)
- fun jsonDeserialization_noId_threwException() {
- val expected = ClockSettings(null, null).apply { _applied_timestamp = 500 }
- val actual = ClockSettings.deserialize("{\"_applied_timestamp\":500}")
+ @Test
+ fun jsonDeserialization_noId_deserializedEmpty() {
+ val expected = ClockSettings(null, null).apply {
+ metadata.put("appliedTimestamp", 500)
+ }
+ val actual = ClockSettings.deserialize("{\"metadata\":{\"appliedTimestamp\":500}}")
assertEquals(expected, actual)
}
@Test
fun jsonSerialization_gotExpectedString() {
- val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}"
- val actual = ClockSettings.serialize(ClockSettings("ID", null)
- .apply { _applied_timestamp = 500 })
+ val expected = "{\"clockId\":\"ID\",\"metadata\":{\"appliedTimestamp\":500}}"
+ val actual = ClockSettings.serialize(ClockSettings("ID", null).apply {
+ metadata.put("appliedTimestamp", 500)
+ })
assertEquals(expected, actual)
}
@Test
fun jsonSerialization_noTimestamp_gotExpectedString() {
- val expected = "{\"clockId\":\"ID\"}"
+ val expected = "{\"clockId\":\"ID\",\"metadata\":{}}"
val actual = ClockSettings.serialize(ClockSettings("ID", null))
assertEquals(expected, actual)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index cd2efc0..7fa27f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -26,6 +26,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ClockSettings
import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -40,7 +41,6 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.notNull
import org.mockito.Mock
import org.mockito.Mockito.never
@@ -97,13 +97,14 @@
@Test
fun defaultClock_initialize() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
- verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
- verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
clock.initialize(resources, 0f, 0f)
- verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
- verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+ val expectedColor = 0
+ verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
verify(mockSmallClockView).onTimeZoneChanged(notNull())
verify(mockLargeClockView).onTimeZoneChanged(notNull())
verify(mockSmallClockView).refreshTime()
@@ -159,15 +160,31 @@
@Test
fun defaultClock_events_onColorPaletteChanged() {
+ val expectedColor = 0
val clock = provider.createClock(DEFAULT_CLOCK_ID)
- verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
- verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
clock.events.onColorPaletteChanged(resources)
- verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
- verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+ verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
+ }
+
+ @Test
+ fun defaultClock_events_onSeedColorChanged() {
+ val initSeedColor = 10
+ val newSeedColor = 20
+ val clock = provider.createClock(ClockSettings(DEFAULT_CLOCK_ID, initSeedColor))
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, initSeedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, initSeedColor)
+
+ clock.events.onSeedColorChanged(newSeedColor)
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, newSeedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, newSeedColor)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
index 4478039..64e58d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
@@ -49,6 +49,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.wm.shell.util.TransitionUtil;
import org.junit.Before;
import org.junit.Test;
@@ -120,7 +121,7 @@
change.setTaskInfo(createTaskInfo(1 /* taskId */, ACTIVITY_TYPE_HOME));
change.setEndAbsBounds(endBounds);
change.setEndRelOffset(0, 0);
- RemoteAnimationTarget wrapped = RemoteAnimationTargetCompat.newTarget(
+ RemoteAnimationTarget wrapped = TransitionUtil.newTarget(
change, 0 /* order */, tinfo, mock(SurfaceControl.Transaction.class), null);
assertEquals(ACTIVITY_TYPE_HOME, wrapped.windowConfiguration.getActivityType());
assertEquals(new Rect(0, 0, 100, 140), wrapped.localBounds);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index d99cdd51..ab615f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -211,16 +211,6 @@
}
@Test
- fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
- whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
- false)
- transitionController.goToLockedShade(null)
- verify(statusbarStateController, never()).setState(anyInt())
- verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
- verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
- }
-
- @Test
fun testTriggeringBouncerNoNotificationsOnLockscreen() {
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
transitionController.goToLockedShade(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
new file mode 100644
index 0000000..7a67796
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 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.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.statusbar.StatusBarState
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorLoggerTest : SysuiTestCase() {
+
+ private val logBufferCounter = LogBufferCounter()
+ private lateinit var logger: NotificationWakeUpCoordinatorLogger
+
+ private fun verifyDidLog(times: Int) {
+ logBufferCounter.verifyDidLog(times)
+ }
+
+ @Before
+ fun setup() {
+ logger = NotificationWakeUpCoordinatorLogger(logBufferCounter.logBuffer)
+ }
+
+ @Test
+ fun setDozeAmountWillThrottleFractionalUpdates() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(1f, 1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ }
+
+ @Test
+ fun setDozeAmountWillIncludeFractionalUpdatesWhenStateChanges() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.KEYGUARD, changed = false)
+ verifyDidLog(1)
+ }
+
+ @Test
+ fun setDozeAmountWillIncludeFractionalUpdatesWhenSourceChanges() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source2", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ }
+
+ class LogBufferCounter {
+ val recentLogs = mutableListOf<Pair<String, LogLevel>>()
+ val tracker =
+ object : LogcatEchoTracker {
+ override val logInBackgroundThread: Boolean = false
+ override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = false
+ override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+ recentLogs.add(tagName to level)
+ return true
+ }
+ }
+ val logBuffer =
+ LogBuffer(name = "test", maxSize = 1, logcatEchoTracker = tracker, systrace = false)
+
+ fun verifyDidLog(times: Int) {
+ assertThat(recentLogs).hasSize(times)
+ recentLogs.clear()
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
new file mode 100644
index 0000000..95591a4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 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.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorTest : SysuiTestCase() {
+
+ private val dumpManager: DumpManager = mock()
+ private val headsUpManager: HeadsUpManager = mock()
+ private val statusBarStateController: StatusBarStateController = mock()
+ private val bypassController: KeyguardBypassController = mock()
+ private val dozeParameters: DozeParameters = mock()
+ private val screenOffAnimationController: ScreenOffAnimationController = mock()
+ private val logger: NotificationWakeUpCoordinatorLogger = mock()
+ private val stackScrollerController: NotificationStackScrollLayoutController = mock()
+
+ private lateinit var notificationWakeUpCoordinator: NotificationWakeUpCoordinator
+ private lateinit var statusBarStateCallback: StatusBarStateController.StateListener
+ private lateinit var bypassChangeCallback: KeyguardBypassController.OnBypassStateChangedListener
+
+ private var bypassEnabled: Boolean = false
+ private var statusBarState: Int = StatusBarState.KEYGUARD
+ private var dozeAmount: Float = 0f
+
+ private fun setBypassEnabled(enabled: Boolean) {
+ bypassEnabled = enabled
+ bypassChangeCallback.onBypassStateChanged(enabled)
+ }
+
+ private fun setStatusBarState(state: Int) {
+ statusBarState = state
+ statusBarStateCallback.onStateChanged(state)
+ }
+
+ private fun setDozeAmount(dozeAmount: Float) {
+ this.dozeAmount = dozeAmount
+ statusBarStateCallback.onDozeAmountChanged(dozeAmount, dozeAmount)
+ }
+
+ @Before
+ fun setup() {
+ whenever(bypassController.bypassEnabled).then { bypassEnabled }
+ whenever(statusBarStateController.state).then { statusBarState }
+ notificationWakeUpCoordinator =
+ NotificationWakeUpCoordinator(
+ dumpManager,
+ headsUpManager,
+ statusBarStateController,
+ bypassController,
+ dozeParameters,
+ screenOffAnimationController,
+ logger,
+ )
+ statusBarStateCallback = withArgCaptor {
+ verify(statusBarStateController).addCallback(capture())
+ }
+ bypassChangeCallback = withArgCaptor {
+ verify(bypassController).registerOnBypassStateChangedListener(capture())
+ }
+ notificationWakeUpCoordinator.setStackScroller(stackScrollerController)
+ }
+
+ @Test
+ fun setDozeToOneWillFullyHideNotifications() {
+ setDozeAmount(1f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+ }
+
+ @Test
+ fun setDozeToZeroWillFullyShowNotifications() {
+ setDozeAmount(0f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun setDozeToOneThenZeroWillFullyShowNotifications() {
+ setDozeToOneWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setDozeToZeroWillFullyShowNotifications()
+ }
+
+ @Test
+ fun setDozeToHalfWillHalfShowNotifications() {
+ setDozeAmount(0.5f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun setDozeToZeroWithBypassWillFullyHideNotifications() {
+ bypassEnabled = true
+ setDozeAmount(0f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 01f, hideAmount = 1f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+ }
+
+ @Test
+ fun disablingBypassWillShowNotifications() {
+ setDozeToZeroWithBypassWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setBypassEnabled(false)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun switchingToShadeWithBypassEnabledWillShowNotifications() {
+ setDozeToZeroWithBypassWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setStatusBarState(StatusBarState.SHADE)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ assertThat(notificationWakeUpCoordinator.statusBarState).isEqualTo(StatusBarState.SHADE)
+ }
+
+ private fun verifyStackScrollerDozeAndHideAmount(dozeAmount: Float, hideAmount: Float) {
+ // First verify that we did in-fact receive the correct values
+ verify(stackScrollerController).setDozeAmount(dozeAmount)
+ verify(stackScrollerController).setHideAmount(hideAmount, hideAmount)
+ // Now verify that there was just this ONE call to each of these methods
+ verify(stackScrollerController).setDozeAmount(anyFloat())
+ verify(stackScrollerController).setHideAmount(anyFloat(), anyFloat())
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 5b8305d..89c399b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -415,6 +415,37 @@
verify(mNotificationStackScrollLayout).updateEmptyShadeView(anyBoolean(), anyBoolean());
}
+ @Test
+ public void testAttach_updatesViewStatusBarState() {
+ // GIVEN: Controller is attached
+ mController.attach(mNotificationStackScrollLayout);
+ ArgumentCaptor<StatusBarStateController.StateListener> captor =
+ ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
+ verify(mSysuiStatusBarStateController).addCallback(captor.capture(), anyInt());
+ StatusBarStateController.StateListener stateListener = captor.getValue();
+
+ // WHEN: StatusBarState changes to SHADE
+ when(mSysuiStatusBarStateController.getState()).thenReturn(SHADE);
+ stateListener.onStateChanged(SHADE);
+
+ // THEN: NSSL is updated with the current state
+ verify(mNotificationStackScrollLayout).setStatusBarState(SHADE);
+
+ // WHEN: Controller is detached
+ mController.mOnAttachStateChangeListener
+ .onViewDetachedFromWindow(mNotificationStackScrollLayout);
+
+ // WHEN: StatusBarState changes to KEYGUARD
+ when(mSysuiStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+ // WHEN: Controller is re-attached
+ mController.mOnAttachStateChangeListener
+ .onViewAttachedToWindow(mNotificationStackScrollLayout);
+
+ // THEN: NSSL is updated with the current state
+ verify(mNotificationStackScrollLayout).setStatusBarState(KEYGUARD);
+ }
+
private LogMaker logMatcher(int category, int type) {
return argThat(new LogMatcher(category, type));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 680a323..78da782 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -20,6 +20,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -227,14 +228,154 @@
}
@Test
- public void testHandleUpEvent_menuRow() {
- when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
- doNothing().when(mSwipeHelper).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+ public void testHandleUpEvent_menuRowWithoutMenu_dismiss() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
assertTrue("Menu row exists",
mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
verify(mMenuRow, times(1)).onTouchEnd();
- verify(mSwipeHelper, times(1)).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithoutMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithOpenMenu_dismissed() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithOpenMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithClosedMenu_dismissed() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithClosedMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(true).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertTrue("Should be a dismiss gesture", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_falseGesture() {
+ doReturn(true).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(true).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertFalse("False gesture should stop dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_farEnough() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(false).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertTrue("Should be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_notFarOrFastEnough() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(false).when(mSwipeHelper).swipedFarEnough();
+ doReturn(false).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertFalse("Should not be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index a168432..c4ee326 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -1080,6 +1080,17 @@
}
@Test
+ public void testSetDozingNotUnlocking_transitionToAuthScrimmed_cancelKeyguardFadingAway() {
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+ when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
+
+ mCentralSurfaces.updateScrimController();
+
+ verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED_SHADE));
+ verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
+ }
+
+ @Test
public void testShowKeyguardImplementation_setsState() {
when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(new SparseArray<>());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 305b9fe..6b18169 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone
import android.app.AlarmManager
-import android.app.IActivityManager
import android.app.admin.DevicePolicyManager
import android.content.SharedPreferences
import android.os.UserManager
@@ -87,7 +86,6 @@
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var locationController: LocationController
@Mock private lateinit var sensorPrivacyController: SensorPrivacyController
- @Mock private lateinit var iActivityManager: IActivityManager
@Mock private lateinit var alarmManager: AlarmManager
@Mock private lateinit var userManager: UserManager
@Mock private lateinit var userTracker: UserTracker
@@ -176,6 +174,7 @@
commandQueue,
broadcastDispatcher,
executor,
+ executor,
testableLooper.looper,
context.resources,
castController,
@@ -190,7 +189,6 @@
keyguardStateController,
locationController,
sensorPrivacyController,
- iActivityManager,
alarmManager,
userManager,
userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 00ce412..b072dee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -239,6 +239,7 @@
* list2 = [false, true]
* list3 = [a, b, c]
* ```
+ *
* We'll generate test cases for:
*
* Test (1, false, a) Test (2, false, a) Test (3, false, a) Test (1, true, a) Test (1,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
@@ -5,4 +5,6 @@
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
index 5288608..0413d92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
@@ -25,7 +25,6 @@
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.util.TestFoldStateProvider
import org.junit.Before
import org.junit.Test
@@ -50,7 +49,7 @@
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -67,7 +66,7 @@
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -84,7 +83,7 @@
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
)
with(listener.ensureTransitionFinished()) {
@@ -113,7 +112,7 @@
fun testUnfoldAndStopUnfolding_finishesTheUnfoldTransition() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN) },
@@ -129,7 +128,7 @@
fun testFoldImmediatelyAfterUnfold_runsFoldAnimation() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
index 6086e16..8476d0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider
import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
+import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
@@ -71,6 +72,7 @@
private val foldUpdates: MutableList<Int> = arrayListOf()
private val hingeAngleUpdates: MutableList<Float> = arrayListOf()
+ private val unfoldedScreenAvailabilityUpdates: MutableList<Unit> = arrayListOf()
private var scheduledRunnable: Runnable? = null
private var scheduledRunnableDelay: Long? = null
@@ -106,6 +108,10 @@
override fun onFoldUpdate(update: Int) {
foldUpdates.add(update)
}
+
+ override fun onUnfoldedScreenAvailable() {
+ unfoldedScreenAvailabilityUpdates.add(Unit)
+ }
})
foldStateProvider.start()
@@ -156,8 +162,8 @@
sendHingeAngleEvent(10)
screenOnStatusProvider.notifyScreenTurnedOn()
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -174,8 +180,9 @@
sendHingeAngleEvent(40)
sendHingeAngleEvent(10)
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE, FOLD_UPDATE_START_CLOSING)
+ assertThat(foldUpdates)
+ .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -223,7 +230,7 @@
fireScreenOnEvent()
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -277,7 +284,7 @@
@Test
fun startClosingEvent_afterTimeout_finishHalfOpenEventEmitted() {
- sendHingeAngleEvent(90)
+ setInitialHingeAngle(90)
sendHingeAngleEvent(80)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS)
@@ -288,7 +295,7 @@
@Test
fun startClosingEvent_beforeTimeout_abortNotEmitted() {
- sendHingeAngleEvent(90)
+ setInitialHingeAngle(90)
sendHingeAngleEvent(80)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -298,7 +305,7 @@
@Test
fun startClosingEvent_eventBeforeTimeout_oneEventEmitted() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -309,7 +316,7 @@
@Test
fun startClosingEvent_timeoutAfterTimeoutRescheduled_finishHalfOpenStateEmitted() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
// The timeout should not trigger here.
@@ -323,7 +330,7 @@
@Test
fun startClosingEvent_shortTimeBetween_emitsOnlyOneEvents() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
sendHingeAngleEvent(80)
@@ -334,20 +341,19 @@
@Test
fun startClosingEvent_whileClosing_emittedDespiteInitialAngle() {
val maxAngle = 180 - FULLY_OPEN_THRESHOLD_DEGREES.toInt()
- for (i in 1..maxAngle) {
- foldUpdates.clear()
-
- simulateFolding(startAngle = i)
+ val minAngle = Math.ceil(HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toDouble()).toInt() + 1
+ for (startAngle in minAngle..maxAngle) {
+ setInitialHingeAngle(startAngle)
+ sendHingeAngleEvent(startAngle - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
- simulateTimeout() // Timeout to set the state to aborted.
}
}
@Test
fun startClosingEvent_whileNotOnLauncher_doesNotTriggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -357,7 +363,7 @@
@Test
fun startClosingEvent_whileActivityTypeNotAvailable_triggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = null)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -367,7 +373,7 @@
@Test
fun startClosingEvent_whileOnLauncher_doesTriggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = true)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -377,9 +383,11 @@
@Test
fun startClosingEvent_whileNotOnLauncher_triggersAfterThreshold() {
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+ setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+ sendHingeAngleEvent(
+ START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+ HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@@ -388,7 +396,7 @@
fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
setKeyguardVisibility(visible = false)
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -398,7 +406,7 @@
@Test
fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
setKeyguardVisibility(visible = null)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -408,7 +416,7 @@
@Test
fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
setKeyguardVisibility(visible = true)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -418,9 +426,59 @@
@Test
fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
setKeyguardVisibility(visible = false)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+ setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+ sendHingeAngleEvent(
+ START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+ HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_doesNotTriggerBelowThreshold() {
+ val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+ setInitialHingeAngle(180)
+ sendHingeAngleEvent(thresholdAngle + 1)
+
+ assertThat(foldUpdates).isEmpty()
+ }
+
+ @Test
+ fun startClosingEvent_triggersAfterThreshold() {
+ val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+ setInitialHingeAngle(180)
+ sendHingeAngleEvent(thresholdAngle + 1)
+ sendHingeAngleEvent(thresholdAngle - 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_triggersAfterThreshold_fromHalfOpen() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES + 1).toInt())
+ assertThat(foldUpdates).isEmpty()
+ sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES - 1).toInt())
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startOpeningAndClosingEvents_triggerWithOpenAndClose() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent(130)
+ sendHingeAngleEvent(120)
+ assertThat(foldUpdates)
+ .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_notInterrupted_whenAngleIsSlightlyIncreased() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent(110)
+ sendHingeAngleEvent(111)
+ sendHingeAngleEvent(100)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@@ -504,11 +562,6 @@
}
}
- private fun simulateFolding(startAngle: Int) {
- sendHingeAngleEvent(startAngle)
- sendHingeAngleEvent(startAngle - 1)
- }
-
private fun setFoldState(folded: Boolean) {
foldProvider.notifyFolded(folded)
}
@@ -521,6 +574,17 @@
testHingeAngleProvider.notifyAngle(angle.toFloat())
}
+ private fun setInitialHingeAngle(angle: Int) {
+ setFoldState(angle == 0)
+ sendHingeAngleEvent(angle)
+ if (scheduledRunnableDelay != null) {
+ simulateTimeout()
+ }
+ hingeAngleUpdates.clear()
+ foldUpdates.clear()
+ unfoldedScreenAvailabilityUpdates.clear()
+ }
+
private class TestFoldProvider : FoldProvider {
private val callbacks = arrayListOf<FoldCallback>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
index a064e8c..fbb0e5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
@@ -57,4 +57,8 @@
fun sendHingeAngleUpdate(angle: Float) {
listeners.forEach { it.onHingeAngleUpdate(angle) }
}
+
+ fun sendUnfoldedScreenAvailable() {
+ listeners.forEach { it.onUnfoldedScreenAvailable() }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index 9312643..e2f3cf7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -17,10 +17,7 @@
package com.android.systemui.user.data.repository
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
import android.content.pm.UserInfo
-import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
@@ -44,14 +41,8 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.anyString
import org.mockito.Mockito.mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -60,8 +51,6 @@
class UserRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var manager: UserManager
- @Mock private lateinit var activityManager: IActivityManager
- @Captor private lateinit var userSwitchObserver: ArgumentCaptor<UserSwitchObserver>
private lateinit var underTest: UserRepositoryImpl
@@ -235,30 +224,31 @@
}
@Test
- fun userSwitchingInProgress_registersOnlyOneUserSwitchObserver() = runSelfCancelingTest {
+ fun userSwitchingInProgress_registersUserTrackerCallback() = runSelfCancelingTest {
underTest = create(this)
underTest.userSwitchingInProgress.launchIn(this)
underTest.userSwitchingInProgress.launchIn(this)
underTest.userSwitchingInProgress.launchIn(this)
- verify(activityManager, times(1)).registerUserSwitchObserver(any(), anyString())
+ // Two callbacks registered - one for observing user switching and one for observing the
+ // selected user
+ assertThat(tracker.callbacks.size).isEqualTo(2)
}
@Test
- fun userSwitchingInProgress_propagatesStateFromActivityManager() = runSelfCancelingTest {
+ fun userSwitchingInProgress_propagatesStateFromUserTracker() = runSelfCancelingTest {
underTest = create(this)
- verify(activityManager)
- .registerUserSwitchObserver(userSwitchObserver.capture(), anyString())
+ assertThat(tracker.callbacks.size).isEqualTo(2)
- userSwitchObserver.value.onUserSwitching(0, mock(IRemoteCallback::class.java))
+ tracker.onUserChanging(0)
var mostRecentSwitchingValue = false
underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
assertThat(mostRecentSwitchingValue).isTrue()
- userSwitchObserver.value.onUserSwitchComplete(0)
+ tracker.onUserChanged(0)
assertThat(mostRecentSwitchingValue).isFalse()
}
@@ -338,7 +328,6 @@
backgroundDispatcher = IMMEDIATE,
globalSettings = globalSettings,
tracker = tracker,
- activityManager = activityManager,
featureFlags = featureFlags,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
index 9b4f496..c2947b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
@@ -29,6 +29,7 @@
/**
* Collect [flow] in a new [Job] and return a getter for the last collected value.
+ *
* ```
* fun myTest() = runTest {
* // ...
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
index 01dac36..d4b1701 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
@@ -21,6 +21,7 @@
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.flowOf
class FakeBiometricSettingsRepository : BiometricSettingsRepository {
@@ -42,6 +43,9 @@
override val isFingerprintEnabledByDevicePolicy =
_isFingerprintEnabledByDevicePolicy.asStateFlow()
+ override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+ get() = flowOf(true)
+
fun setFingerprintEnrolled(isFingerprintEnrolled: Boolean) {
_isFingerprintEnrolled.value = isFingerprintEnrolled
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
new file mode 100644
index 0000000..914c786
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 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.keyguard.data.repository
+
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeDevicePostureRepository : DevicePostureRepository {
+ private val _currentDevicePosture = MutableStateFlow(DevicePosture.UNKNOWN)
+ override val currentDevicePosture: Flow<DevicePosture>
+ get() = _currentDevicePosture
+
+ fun setCurrentPosture(posture: DevicePosture) {
+ _currentDevicePosture.value = posture
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index 251014f..4242c16 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -22,6 +22,7 @@
import android.os.UserHandle
import android.test.mock.MockContentResolver
import com.android.systemui.util.mockito.mock
+import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
/** A fake [UserTracker] to be used in tests. */
@@ -66,11 +67,19 @@
_userId = _userInfo.id
_userHandle = UserHandle.of(_userId)
+ onUserChanging()
+ onUserChanged()
+ }
+
+ fun onUserChanging(userId: Int = _userId) {
val copy = callbacks.toList()
- copy.forEach {
- it.onUserChanging(_userId, userContext)
- it.onUserChanged(_userId, userContext)
- }
+ val latch = CountDownLatch(copy.size)
+ copy.forEach { it.onUserChanging(userId, userContext, latch) }
+ }
+
+ fun onUserChanged(userId: Int = _userId) {
+ val copy = callbacks.toList()
+ copy.forEach { it.onUserChanged(userId, userContext) }
}
fun onProfileChanged() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
new file mode 100644
index 0000000..0c9ce0f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 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.util
+
+import android.content.DialogInterface
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.verify
+import org.mockito.stubbing.Stubber
+
+class FakeSystemUIDialogController {
+
+ val dialog: SystemUIDialog = mock()
+
+ private val clickListeners: MutableMap<Int, DialogInterface.OnClickListener> = mutableMapOf()
+
+ init {
+ saveListener(DialogInterface.BUTTON_POSITIVE)
+ .whenever(dialog)
+ .setPositiveButton(any(), any())
+ saveListener(DialogInterface.BUTTON_POSITIVE)
+ .whenever(dialog)
+ .setPositiveButton(any(), any(), any())
+
+ saveListener(DialogInterface.BUTTON_NEGATIVE)
+ .whenever(dialog)
+ .setNegativeButton(any(), any())
+ saveListener(DialogInterface.BUTTON_NEGATIVE)
+ .whenever(dialog)
+ .setNegativeButton(any(), any(), any())
+
+ saveListener(DialogInterface.BUTTON_NEUTRAL).whenever(dialog).setNeutralButton(any(), any())
+ saveListener(DialogInterface.BUTTON_NEUTRAL)
+ .whenever(dialog)
+ .setNeutralButton(any(), any(), any())
+ }
+
+ fun clickNegative() {
+ performClick(DialogInterface.BUTTON_NEGATIVE, "This dialog has no negative button")
+ }
+
+ fun clickPositive() {
+ performClick(DialogInterface.BUTTON_POSITIVE, "This dialog has no positive button")
+ }
+
+ fun clickNeutral() {
+ performClick(DialogInterface.BUTTON_NEUTRAL, "This dialog has no neutral button")
+ }
+
+ fun cancel() {
+ val captor = ArgumentCaptor.forClass(DialogInterface.OnCancelListener::class.java)
+ verify(dialog).setOnCancelListener(captor.capture())
+ captor.value.onCancel(dialog)
+ }
+
+ private fun performClick(which: Int, errorMessage: String) {
+ clickListeners
+ .getOrElse(which) { throw IllegalAccessException(errorMessage) }
+ .onClick(dialog, which)
+ }
+
+ private fun saveListener(which: Int): Stubber = doAnswer {
+ val listener = it.getArgument<DialogInterface.OnClickListener>(1)
+ clickListeners[which] = listener
+ Unit
+ }
+}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
index 4622464..c437e5c 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
@@ -21,7 +21,6 @@
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import javax.inject.Inject
@@ -59,12 +58,15 @@
}
override fun onFoldUpdate(@FoldUpdate update: Int) {
- when (update) {
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> animator.start()
- FOLD_UPDATE_FINISH_CLOSED -> animator.cancel()
+ if (update == FOLD_UPDATE_FINISH_CLOSED) {
+ animator.cancel()
}
}
+ override fun onUnfoldedScreenAvailable() {
+ animator.start()
+ }
+
override fun addCallback(listener: TransitionProgressListener) {
listeners.add(listener)
}
@@ -73,8 +75,6 @@
listeners.remove(listener)
}
- override fun onHingeAngleUpdate(angle: Float) {}
-
private object AnimationProgressProperty :
FloatProperty<FixedTimingTransitionProgressProvider>("animation_progress") {
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 6ffbe5a..d19b414 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -28,7 +28,6 @@
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
@@ -78,21 +77,11 @@
override fun onFoldUpdate(@FoldUpdate update: Int) {
when (update) {
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> {
- startTransition(startValue = 0f)
-
- // Stop the animation if the device has already opened by the time when
- // the display is available as we won't receive the full open event anymore
- if (foldStateProvider.isFinishedOpening) {
- cancelTransition(endValue = 1f, animate = true)
- }
- }
FOLD_UPDATE_FINISH_FULL_OPEN, FOLD_UPDATE_FINISH_HALF_OPEN -> {
// Do not cancel if we haven't started the transition yet.
// This could happen when we fully unfolded the device before the screen
// became available. In this case we start and immediately cancel the animation
- // in FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE event handler, so we don't need to
- // cancel it here.
+ // in onUnfoldedScreenAvailable event handler, so we don't need to cancel it here.
if (isTransitionRunning) {
cancelTransition(endValue = 1f, animate = true)
}
@@ -125,6 +114,16 @@
}
}
+ override fun onUnfoldedScreenAvailable() {
+ startTransition(startValue = 0f)
+
+ // Stop the animation if the device has already opened by the time when
+ // the display is available as we won't receive the full open event anymore
+ if (foldStateProvider.isFinishedOpening) {
+ cancelTransition(endValue = 1f, animate = true)
+ }
+ }
+
private fun cancelTransition(endValue: Float, animate: Boolean) {
if (isTransitionRunning && animate) {
if (endValue == 1.0f && !isAnimatedCancelRunning) {
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 97c9ba9..82fd225 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -54,6 +54,7 @@
@FoldUpdate private var lastFoldUpdate: Int? = null
@FloatRange(from = 0.0, to = 180.0) private var lastHingeAngle: Float = 0f
+ @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngleBeforeTransition: Float = 0f
private val hingeAngleListener = HingeAngleListener()
private val screenListener = ScreenStatusListener()
@@ -112,29 +113,45 @@
private fun onHingeAngle(angle: Float) {
if (DEBUG) {
- Log.d(TAG, "Hinge angle: $angle, lastHingeAngle: $lastHingeAngle")
+ Log.d(
+ TAG,
+ "Hinge angle: $angle, " +
+ "lastHingeAngle: $lastHingeAngle, " +
+ "lastHingeAngleBeforeTransition: $lastHingeAngleBeforeTransition"
+ )
Trace.traceCounter(Trace.TRACE_TAG_APP, "hinge_angle", angle.toInt())
}
- val isClosing = angle < lastHingeAngle
+ val currentDirection =
+ if (angle < lastHingeAngle) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+ if (isTransitionInProgress && currentDirection != lastFoldUpdate) {
+ lastHingeAngleBeforeTransition = lastHingeAngle
+ }
+
+ val isClosing = angle < lastHingeAngleBeforeTransition
+ val transitionUpdate =
+ if (isClosing) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+ val angleChangeSurpassedThreshold =
+ Math.abs(angle - lastHingeAngleBeforeTransition) > HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES
val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
- val closingEventDispatched = lastFoldUpdate == FOLD_UPDATE_START_CLOSING
+ val eventNotAlreadyDispatched = lastFoldUpdate != transitionUpdate
val screenAvailableEventSent = isUnfoldHandled
- if (isClosing // hinge angle should be decreasing since last update
- && !closingEventDispatched // we haven't sent closing event already
- && !isFullyOpened // do not send closing event if we are in fully opened hinge
+ if (
+ angleChangeSurpassedThreshold && // Do not react immediately to small changes in angle
+ eventNotAlreadyDispatched && // we haven't sent transition event already
+ !isFullyOpened && // do not send transition event if we are in fully opened hinge
// angle range as closing threshold could overlap this range
- && screenAvailableEventSent // do not send closing event if we are still in
- // the process of turning on the inner display
- && isClosingThresholdMet(angle) // hinge angle is below certain threshold.
+ screenAvailableEventSent && // do not send transition event if we are still in the
+ // process of turning on the inner display
+ isClosingThresholdMet(angle) // hinge angle is below certain threshold.
) {
- notifyFoldUpdate(FOLD_UPDATE_START_CLOSING)
+ notifyFoldUpdate(transitionUpdate, lastHingeAngle)
}
if (isTransitionInProgress) {
if (isFullyOpened) {
- notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN)
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN, angle)
cancelTimeout()
} else {
// The timeout will trigger some constant time after the last angle update.
@@ -146,7 +163,7 @@
outputListeners.forEach { it.onHingeAngleUpdate(angle) }
}
- private fun isClosingThresholdMet(currentAngle: Float) : Boolean {
+ private fun isClosingThresholdMet(currentAngle: Float): Boolean {
val closingThreshold = getClosingThreshold()
return closingThreshold == null || currentAngle < closingThreshold
}
@@ -179,23 +196,29 @@
if (isFolded) {
hingeAngleProvider.stop()
- notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED, lastHingeAngle)
cancelTimeout()
isUnfoldHandled = false
} else {
- notifyFoldUpdate(FOLD_UPDATE_START_OPENING)
+ notifyFoldUpdate(FOLD_UPDATE_START_OPENING, lastHingeAngle)
rescheduleAbortAnimationTimeout()
hingeAngleProvider.start()
}
}
}
- private fun notifyFoldUpdate(@FoldUpdate update: Int) {
+ private fun notifyFoldUpdate(@FoldUpdate update: Int, angle: Float) {
if (DEBUG) {
Log.d(TAG, update.name())
}
+ val previouslyTransitioning = isTransitionInProgress
+
outputListeners.forEach { it.onFoldUpdate(update) }
lastFoldUpdate = update
+
+ if (previouslyTransitioning != isTransitionInProgress) {
+ lastHingeAngleBeforeTransition = angle
+ }
}
private fun rescheduleAbortAnimationTimeout() {
@@ -209,7 +232,8 @@
handler.removeCallbacks(timeoutRunnable)
}
- private fun cancelAnimation(): Unit = notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN)
+ private fun cancelAnimation(): Unit =
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN, lastHingeAngle)
private inner class ScreenStatusListener : ScreenStatusProvider.ScreenListener {
@@ -221,7 +245,7 @@
// receive 'folded' event. If SystemUI started when device is already folded it will
// still receive 'folded' event on startup.
if (!isFolded && !isUnfoldHandled) {
- outputListeners.forEach { it.onFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) }
+ outputListeners.forEach { it.onUnfoldedScreenAvailable() }
isUnfoldHandled = true
}
}
@@ -257,7 +281,6 @@
when (this) {
FOLD_UPDATE_START_OPENING -> "START_OPENING"
FOLD_UPDATE_START_CLOSING -> "START_CLOSING"
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> "UNFOLDED_SCREEN_AVAILABLE"
FOLD_UPDATE_FINISH_HALF_OPEN -> "FINISH_HALF_OPEN"
FOLD_UPDATE_FINISH_FULL_OPEN -> "FINISH_FULL_OPEN"
FOLD_UPDATE_FINISH_CLOSED -> "FINISH_CLOSED"
@@ -270,5 +293,8 @@
/** Threshold after which we consider the device fully unfolded. */
@VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
+/** Threshold after which hinge angle updates are considered. This is to eliminate noise. */
+@VisibleForTesting const val HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES = 7.5f
+
/** Fold animation on top of apps only when the angle exceeds this threshold. */
@VisibleForTesting const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
index c7a8bf3..0af372f 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
@@ -31,8 +31,9 @@
val isFinishedOpening: Boolean
interface FoldUpdatesListener {
- fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float)
- fun onFoldUpdate(@FoldUpdate update: Int)
+ @JvmDefault fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float) {}
+ @JvmDefault fun onFoldUpdate(@FoldUpdate update: Int) {}
+ @JvmDefault fun onUnfoldedScreenAvailable() {}
}
@IntDef(
@@ -40,7 +41,6 @@
[
FOLD_UPDATE_START_OPENING,
FOLD_UPDATE_START_CLOSING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE,
FOLD_UPDATE_FINISH_HALF_OPEN,
FOLD_UPDATE_FINISH_FULL_OPEN,
FOLD_UPDATE_FINISH_CLOSED])
@@ -50,7 +50,6 @@
const val FOLD_UPDATE_START_OPENING = 0
const val FOLD_UPDATE_START_CLOSING = 1
-const val FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE = 2
-const val FOLD_UPDATE_FINISH_HALF_OPEN = 3
-const val FOLD_UPDATE_FINISH_FULL_OPEN = 4
-const val FOLD_UPDATE_FINISH_CLOSED = 5
+const val FOLD_UPDATE_FINISH_HALF_OPEN = 2
+const val FOLD_UPDATE_FINISH_FULL_OPEN = 3
+const val FOLD_UPDATE_FINISH_CLOSED = 4
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
index b7bab3e..f9751d9 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
@@ -47,6 +47,7 @@
/**
* Sets the source for the unfold transition progress updates. Replaces current provider if it
* is already set
+ *
* @param provider transition provider that emits transition progress updates
*/
fun setSourceProvider(provider: UnfoldTransitionProgressProvider?) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index a359216..e159f18 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -1635,7 +1635,7 @@
return false;
}
- if (event.isAccessibilityDataPrivate()
+ if (event.isAccessibilityDataSensitive()
&& (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) {
return false;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
index 86b5a12..a94ab34 100644
--- a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
+++ b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
@@ -53,6 +53,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.Display;
import android.view.View;
@@ -342,10 +343,12 @@
private void requestStartFlashNotification(FlashNotification flashNotification) {
if (DEBUG) Log.d(LOG_TAG, "requestStartFlashNotification");
- mIsCameraFlashNotificationEnabled = Settings.System.getIntForUser(
+ boolean isFeatureOn = FeatureFlagUtils.isEnabled(mContext,
+ FeatureFlagUtils.SETTINGS_FLASH_NOTIFICATIONS);
+ mIsCameraFlashNotificationEnabled = isFeatureOn && Settings.System.getIntForUser(
mContext.getContentResolver(), SETTING_KEY_CAMERA_FLASH_NOTIFICATION, 0,
UserHandle.USER_CURRENT) != 0;
- mIsScreenFlashNotificationEnabled = Settings.System.getIntForUser(
+ mIsScreenFlashNotificationEnabled = isFeatureOn && Settings.System.getIntForUser(
mContext.getContentResolver(), SETTING_KEY_SCREEN_FLASH_NOTIFICATION, 0,
UserHandle.USER_CURRENT) != 0;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 43b816b..61032dc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -849,6 +849,32 @@
}
}
+
+ /**
+ * Updates the last fill response when a view was entered.
+ */
+ void logViewEntered(int sessionId, @Nullable Bundle clientState) {
+ synchronized (mLock) {
+ if (!isValidEventLocked("logViewEntered", sessionId)) {
+ return;
+ }
+
+ if (mEventHistory.getEvents() != null) {
+ // Do not log this event more than once
+ for (Event event : mEventHistory.getEvents()) {
+ if (event.getType() == Event.TYPE_VIEW_REQUESTED_AUTOFILL) {
+ Slog.v(TAG, "logViewEntered: already logged TYPE_VIEW_REQUESTED_AUTOFILL");
+ return;
+ }
+ }
+ }
+
+ mEventHistory.addEvent(
+ new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null,
+ null, null, null, null, null, null, null));
+ }
+ }
+
void logAugmentedAutofillAuthenticationSelected(int sessionId, @Nullable String selectedDataset,
@Nullable Bundle clientState) {
synchronized (mLock) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 598521f..4a12e38 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -442,6 +442,18 @@
private boolean mPreviouslyFillDialogPotentiallyStarted;
/**
+ * Keeps track of if the user entered view, this is used to
+ * distinguish Fill Request that did not have user interaction
+ * with ones that did.
+ *
+ * This is set to true when entering view - after FillDialog FillRequest
+ * or on plain user tap.
+ */
+ @NonNull
+ @GuardedBy("mLock")
+ private boolean mLogViewEntered;
+
+ /**
* Keeps the fill dialog trigger ids of the last response. This invalidates
* the trigger ids of the previous response.
*/
@@ -1289,6 +1301,7 @@
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
+ mLogViewEntered = false;
}
/**
@@ -1413,6 +1426,14 @@
mService.setLastResponse(id, response);
+ synchronized (mLock) {
+ if (mLogViewEntered) {
+ mLogViewEntered = false;
+ mService.logViewEntered(id, null);
+ }
+ }
+
+
final long disableDuration = response.getDisableDuration();
final boolean autofillDisabled = disableDuration > 0;
if (autofillDisabled) {
@@ -3545,6 +3566,28 @@
return;
}
+ synchronized (mLock) {
+ if (!mLogViewEntered) {
+ // If the current request is for FillDialog (preemptive)
+ // then this is the first time that the view is entered
+ // (mLogViewEntered == false) in this case, setLastResponse()
+ // has already been called, so just log here.
+ // If the current request is not and (mLogViewEntered == false)
+ // then the last session is being tracked (setLastResponse not called)
+ // so this calling logViewEntered will be a nop.
+ // Calling logViewEntered() twice will only log it once
+ // TODO(271181979): this is broken for multiple partitions
+ mService.logViewEntered(this.id, null);
+ }
+
+ // If this is the first time view is entered for inline, the last
+ // session is still being tracked, so logViewEntered() needs
+ // to be delayed until setLastResponse is called.
+ // For fill dialog requests case logViewEntered is already called above
+ // so this will do nothing. Assumption: only one fill dialog per session
+ mLogViewEntered = true;
+ }
+
// Previously, fill request will only start whenever a view is entered.
// With Fill Dialog, request starts prior to view getting entered. So, we can't end
// the event at this moment, otherwise we will be wrongly attributing fill dialog
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 79709a3..1176178 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -2,7 +2,6 @@
set noparent
-bryanmawhinney@google.com
jstemmer@google.com
martinoh@google.com
millmore@google.com
diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
index 9f27f72..3fffdbe 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
@@ -23,6 +23,7 @@
import static android.content.ComponentName.createRelative;
import static com.android.server.companion.Utils.prepareForIpc;
+import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -91,7 +92,8 @@
mAssociationStore = associationStore;
mSystemDataTransferRequestStore = systemDataTransferRequestStore;
mTransportManager = transportManager;
- mTransportManager.setListener(this::onReceivePermissionRestore);
+ mTransportManager.addListener(MESSAGE_REQUEST_PERMISSION_RESTORE,
+ this::onReceivePermissionRestore);
mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
mExecutor = Executors.newSingleThreadExecutor();
}
diff --git a/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
index adaee75..1559a3f 100644
--- a/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
+++ b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
@@ -35,7 +35,7 @@
/**
* Helper class to perform attestation verification synchronously.
*/
-class AttestationVerifier {
+public class AttestationVerifier {
private static final long ATTESTATION_VERIFICATION_TIMEOUT_SECONDS = 10; // 10 seconds
private static final String PARAM_OWNED_BY_SYSTEM = "android.key_owned_by_system";
diff --git a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
index 13dba84..05b6022 100644
--- a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
+++ b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
@@ -110,7 +110,7 @@
this(in, out, callback, null, new AttestationVerifier(context));
}
- private SecureChannel(
+ public SecureChannel(
final InputStream in,
final OutputStream out,
Callback callback,
@@ -381,9 +381,10 @@
private void exchangeAuthentication()
throws IOException, GeneralSecurityException, BadHandleException, CryptoException {
- if (mVerifier == null) {
+ if (mPreSharedKey != null) {
exchangePreSharedKey();
- } else {
+ }
+ if (mVerifier != null) {
exchangeAttestation();
}
}
diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
index 6a53adf..8dab231 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -19,9 +19,9 @@
import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES;
import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
+import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PLATFORM_INFO;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManagerInternal;
import android.content.Context;
@@ -30,12 +30,17 @@
import android.os.Binder;
import android.os.Build;
import android.os.ParcelFileDescriptor;
+import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
+import com.android.server.companion.transport.Transport.Listener;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
@@ -44,6 +49,9 @@
private static final String TAG = "CDM_CompanionTransportManager";
private static final boolean DEBUG = false;
+ private static final int SECURE_CHANNEL_AVAILABLE_SDK = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+ private static final int NON_ANDROID = -1;
+
private boolean mSecureTransportEnabled = true;
private static boolean isRequest(int message) {
@@ -54,24 +62,29 @@
return (message & 0xFF000000) == 0x33000000;
}
- public interface Listener {
- void onRequestPermissionRestore(byte[] data);
- }
-
private final Context mContext;
@GuardedBy("mTransports")
private final SparseArray<Transport> mTransports = new SparseArray<>();
- @Nullable
- private Listener mListener;
+ @NonNull
+ private final Map<Integer, Listener> mListeners = new HashMap<>();
+
+ private Transport mTempTransport;
public CompanionTransportManager(Context context) {
mContext = context;
}
- public void setListener(@NonNull Listener listener) {
- mListener = listener;
+ /**
+ * Add a message listener when a message is received for the message type
+ */
+ @GuardedBy("mTransports")
+ public void addListener(int message, @NonNull Listener listener) {
+ mListeners.put(message, listener);
+ for (int i = 0; i < mTransports.size(); i++) {
+ mTransports.valueAt(i).addListener(message, listener);
+ }
}
/**
@@ -105,15 +118,7 @@
detachSystemDataTransport(packageName, userId, associationId);
}
- final Transport transport;
- if (isSecureTransportEnabled(associationId)) {
- transport = new SecureTransport(associationId, fd, mContext, mListener);
- } else {
- transport = new RawTransport(associationId, fd, mContext, mListener);
- }
-
- transport.start();
- mTransports.put(associationId, transport);
+ initializeTransport(associationId, fd);
}
}
@@ -128,13 +133,85 @@
}
}
+ @GuardedBy("mTransports")
+ private void initializeTransport(int associationId, ParcelFileDescriptor fd) {
+ if (!isSecureTransportEnabled()) {
+ Transport transport = new RawTransport(associationId, fd, mContext);
+ for (Map.Entry<Integer, Listener> entry : mListeners.entrySet()) {
+ transport.addListener(entry.getKey(), entry.getValue());
+ }
+ transport.start();
+ mTransports.put(associationId, transport);
+ Slog.i(TAG, "RawTransport is created");
+ return;
+ }
+
+ // Exchange platform info to decide which transport should be created
+ mTempTransport = new RawTransport(associationId, fd, mContext);
+ for (Map.Entry<Integer, Listener> entry : mListeners.entrySet()) {
+ mTempTransport.addListener(entry.getKey(), entry.getValue());
+ }
+ mTempTransport.addListener(MESSAGE_REQUEST_PLATFORM_INFO, this::onPlatformInfoReceived);
+ mTempTransport.start();
+
+ int sdk = Build.VERSION.SDK_INT;
+ String release = Build.VERSION.RELEASE;
+ // data format: | SDK_INT (int) | release length (int) | release |
+ final ByteBuffer data = ByteBuffer.allocate(4 + 4 + release.getBytes().length)
+ .putInt(sdk)
+ .putInt(release.getBytes().length)
+ .put(release.getBytes());
+
+ // TODO: it should check if preSharedKey is given
+ mTempTransport.requestForResponse(MESSAGE_REQUEST_PLATFORM_INFO, data.array());
+ }
+
+ /**
+ * Depending on the remote platform info to decide which transport should be created
+ */
+ @GuardedBy("mTransports")
+ private void onPlatformInfoReceived(byte[] data) {
+ // TODO: it should check if preSharedKey is given
+
+ ByteBuffer buffer = ByteBuffer.wrap(data);
+ int remoteSdk = buffer.getInt();
+ byte[] remoteRelease = new byte[buffer.getInt()];
+ buffer.get(remoteRelease);
+
+ Slog.i(TAG, "Remote device SDK: " + remoteSdk + ", release:" + new String(remoteRelease));
+
+ Transport transport = mTempTransport;
+ mTempTransport = null;
+
+ int sdk = Build.VERSION.SDK_INT;
+ String release = Build.VERSION.RELEASE;
+ if (remoteSdk == NON_ANDROID) {
+ // TODO: pass in a real preSharedKey
+ transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
+ mContext, null, null);
+ } else if (sdk < SECURE_CHANNEL_AVAILABLE_SDK
+ || remoteSdk < SECURE_CHANNEL_AVAILABLE_SDK) {
+ // TODO: depending on the release version, either
+ // 1) using a RawTransport for old T versions
+ // 2) or an Ukey2 handshaked transport for UKey2 backported T versions
+ } else {
+ Slog.i(TAG, "Creating a secure channel");
+ transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
+ mContext);
+ for (Map.Entry<Integer, Listener> entry : mListeners.entrySet()) {
+ transport.addListener(entry.getKey(), entry.getValue());
+ }
+ transport.start();
+ }
+ mTransports.put(transport.getAssociationId(), transport);
+ }
+
public Future<?> requestPermissionRestore(int associationId, byte[] data) {
synchronized (mTransports) {
final Transport transport = mTransports.get(associationId);
if (transport == null) {
return CompletableFuture.failedFuture(new IOException("Missing transport"));
}
-
return transport.requestForResponse(MESSAGE_REQUEST_PERMISSION_RESTORE, data);
}
}
@@ -146,10 +223,9 @@
this.mSecureTransportEnabled = enabled;
}
- private boolean isSecureTransportEnabled(int associationId) {
+ private boolean isSecureTransportEnabled() {
boolean enabled = !Build.IS_DEBUGGABLE || mSecureTransportEnabled;
- // TODO: version comparison logic
return enabled;
}
}
diff --git a/services/companion/java/com/android/server/companion/transport/CryptoManager.java b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
index b08354a..a15939e 100644
--- a/services/companion/java/com/android/server/companion/transport/CryptoManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
@@ -16,51 +16,51 @@
package com.android.server.companion.transport;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
import android.util.Slog;
-import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableEntryException;
-import java.security.cert.CertificateException;
+import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
/**
- * This class can be used to encrypt and decrypt bytes using Android Cryptography
+ * This class uses Java Cryptography to encrypt and decrypt messages
*/
public class CryptoManager {
private static final String TAG = "CDM_CryptoManager";
+ private static final int SECRET_KEY_LENGTH = 32;
+ private static final String ALGORITHM = "AES";
+ private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";
- private static final String KEY_STORE_ALIAS = "cdm_secret";
- private static final String ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
- private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
- private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
- private static final String TRANSFORMATION = ALGORITHM + "/" + BLOCK_MODE + "/" + PADDING;
+ private final byte[] mPreSharedKey;
+ private Cipher mEncryptCipher;
+ private Cipher mDecryptCipher;
- private final KeyStore mKeyStore;
+ private SecretKey mSecretKey;
- public CryptoManager() {
- // Initialize KeyStore
+ public CryptoManager(byte[] preSharedKey) {
+ if (preSharedKey == null) {
+ mPreSharedKey = Arrays.copyOf(new byte[0], SECRET_KEY_LENGTH);
+ } else {
+ mPreSharedKey = Arrays.copyOf(preSharedKey, SECRET_KEY_LENGTH);
+ }
+ mSecretKey = new SecretKeySpec(mPreSharedKey, ALGORITHM);
try {
- mKeyStore = KeyStore.getInstance("AndroidKeyStore");
- mKeyStore.load(null);
- } catch (KeyStoreException | IOException | NoSuchAlgorithmException
- | CertificateException e) {
- throw new RuntimeException(e);
+ mEncryptCipher = Cipher.getInstance(TRANSFORMATION);
+ mEncryptCipher.init(Cipher.ENCRYPT_MODE, mSecretKey);
+ mDecryptCipher = Cipher.getInstance(TRANSFORMATION);
+ } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
+ Slog.e(TAG, e.getMessage());
}
}
@@ -69,21 +69,19 @@
*/
public byte[] encrypt(byte[] input) {
try {
- // Encrypt using Cipher
- Cipher encryptCipher = Cipher.getInstance(TRANSFORMATION);
- encryptCipher.init(Cipher.ENCRYPT_MODE, getKey());
- byte[] encryptedBytes = encryptCipher.doFinal(input);
+ if (mEncryptCipher == null) {
+ return null;
+ }
- // Write to bytes
+ byte[] encryptedBytes = mEncryptCipher.doFinal(input);
ByteBuffer buffer = ByteBuffer.allocate(
- 4 + encryptCipher.getIV().length + 4 + encryptedBytes.length)
- .putInt(encryptCipher.getIV().length)
- .put(encryptCipher.getIV())
+ 4 + mEncryptCipher.getIV().length + 4 + encryptedBytes.length)
+ .putInt(mEncryptCipher.getIV().length)
+ .put(mEncryptCipher.getIV())
.putInt(encryptedBytes.length)
.put(encryptedBytes);
return buffer.array();
- } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
- | IllegalBlockSizeException | BadPaddingException e) {
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
Slog.e(TAG, e.getMessage());
return null;
}
@@ -99,45 +97,20 @@
byte[] encryptedBytes = new byte[buffer.getInt()];
buffer.get(encryptedBytes);
try {
- Cipher decryptCipher = Cipher.getInstance(TRANSFORMATION);
- decryptCipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
- return decryptCipher.doFinal(encryptedBytes);
- } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
- | InvalidAlgorithmParameterException | IllegalBlockSizeException
- | BadPaddingException e) {
+ mDecryptCipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
+ return mDecryptCipher.doFinal(encryptedBytes);
+ } catch (InvalidKeyException | InvalidAlgorithmParameterException
+ | IllegalBlockSizeException | BadPaddingException e) {
Slog.e(TAG, e.getMessage());
return null;
}
}
private SecretKey getKey() {
- try {
- KeyStore.Entry keyEntry = mKeyStore.getEntry(KEY_STORE_ALIAS, null);
- if (keyEntry instanceof KeyStore.SecretKeyEntry
- && ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey() != null) {
- return ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey();
- } else {
- return createKey();
- }
- } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) {
- throw new RuntimeException(e);
+ if (mSecretKey != null) {
+ return mSecretKey;
}
- }
-
- private SecretKey createKey() {
- try {
- KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
- keyGenerator.init(
- new KeyGenParameterSpec.Builder(KEY_STORE_ALIAS,
- KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- .setBlockModes(BLOCK_MODE)
- .setEncryptionPaddings(PADDING)
- .setUserAuthenticationRequired(false)
- .setRandomizedEncryptionRequired(true)
- .build());
- return keyGenerator.generateKey();
- } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
- throw new RuntimeException(e);
- }
+ mSecretKey = new SecretKeySpec(mPreSharedKey, ALGORITHM);
+ return mSecretKey;
}
}
diff --git a/services/companion/java/com/android/server/companion/transport/RawTransport.java b/services/companion/java/com/android/server/companion/transport/RawTransport.java
index 7c0c7cf..4060f6e 100644
--- a/services/companion/java/com/android/server/companion/transport/RawTransport.java
+++ b/services/companion/java/com/android/server/companion/transport/RawTransport.java
@@ -21,8 +21,6 @@
import android.os.ParcelFileDescriptor;
import android.util.Slog;
-import com.android.server.companion.transport.CompanionTransportManager.Listener;
-
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -32,8 +30,8 @@
class RawTransport extends Transport {
private volatile boolean mStopped;
- RawTransport(int associationId, ParcelFileDescriptor fd, Context context, Listener listener) {
- super(associationId, fd, context, listener);
+ RawTransport(int associationId, ParcelFileDescriptor fd, Context context) {
+ super(associationId, fd, context);
}
@Override
@@ -64,7 +62,7 @@
protected void sendMessage(int message, int sequence, @NonNull byte[] data)
throws IOException {
if (DEBUG) {
- Slog.d(TAG, "Sending message 0x" + Integer.toHexString(message)
+ Slog.e(TAG, "Sending message 0x" + Integer.toHexString(message)
+ " sequence " + sequence + " length " + data.length
+ " to association " + mAssociationId);
}
diff --git a/services/companion/java/com/android/server/companion/transport/SecureTransport.java b/services/companion/java/com/android/server/companion/transport/SecureTransport.java
index 4194130..cca0843 100644
--- a/services/companion/java/com/android/server/companion/transport/SecureTransport.java
+++ b/services/companion/java/com/android/server/companion/transport/SecureTransport.java
@@ -21,8 +21,8 @@
import android.os.ParcelFileDescriptor;
import android.util.Slog;
+import com.android.server.companion.securechannel.AttestationVerifier;
import com.android.server.companion.securechannel.SecureChannel;
-import com.android.server.companion.transport.CompanionTransportManager.Listener;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -37,14 +37,17 @@
private final BlockingQueue<byte[]> mRequestQueue = new ArrayBlockingQueue<>(100);
- SecureTransport(int associationId,
- ParcelFileDescriptor fd,
- Context context,
- Listener listener) {
- super(associationId, fd, context, listener);
+ SecureTransport(int associationId, ParcelFileDescriptor fd, Context context) {
+ super(associationId, fd, context);
mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, context);
}
+ SecureTransport(int associationId, ParcelFileDescriptor fd, Context context,
+ byte[] preSharedKey, AttestationVerifier verifier) {
+ super(associationId, fd, context);
+ mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, preSharedKey, verifier);
+ }
+
@Override
public void start() {
mSecureChannel.start();
diff --git a/services/companion/java/com/android/server/companion/transport/Transport.java b/services/companion/java/com/android/server/companion/transport/Transport.java
index 923d424..e984c63 100644
--- a/services/companion/java/com/android/server/companion/transport/Transport.java
+++ b/services/companion/java/com/android/server/companion/transport/Transport.java
@@ -25,23 +25,28 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
-import com.android.server.companion.transport.CompanionTransportManager.Listener;
import libcore.util.EmptyArray;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
-abstract class Transport {
+/**
+ * This class represents the channel established between two devices.
+ */
+public abstract class Transport {
protected static final String TAG = "CDM_CompanionTransport";
protected static final boolean DEBUG = Build.IS_DEBUGGABLE;
static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
- static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
+ public static final int MESSAGE_REQUEST_PLATFORM_INFO = 0x63807086; // ?PFV
+ public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
static final int MESSAGE_RESPONSE_SUCCESS = 0x33838567; // !SUC
static final int MESSAGE_RESPONSE_FAILURE = 0x33706573; // !FAI
@@ -49,11 +54,24 @@
protected static final int HEADER_LENGTH = 12;
protected final int mAssociationId;
+ protected final ParcelFileDescriptor mFd;
protected final InputStream mRemoteIn;
protected final OutputStream mRemoteOut;
protected final Context mContext;
- private final Listener mListener;
+ /** Message type -> Listener */
+ private final Map<Integer, Listener> mListeners;
+
+ /**
+ * Message listener
+ */
+ public interface Listener {
+ /**
+ * Called when a message is received
+ * @param data data content in the message
+ */
+ void onDataReceived(byte[] data);
+ }
private static boolean isRequest(int message) {
return (message & 0xFF000000) == 0x63000000;
@@ -68,16 +86,36 @@
new SparseArray<>();
protected final AtomicInteger mNextSequence = new AtomicInteger();
- Transport(int associationId, ParcelFileDescriptor fd, Context context, Listener listener) {
- this.mAssociationId = associationId;
- this.mRemoteIn = new ParcelFileDescriptor.AutoCloseInputStream(fd);
- this.mRemoteOut = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- this.mContext = context;
- this.mListener = listener;
+ Transport(int associationId, ParcelFileDescriptor fd, Context context) {
+ mAssociationId = associationId;
+ mFd = fd;
+ mRemoteIn = new ParcelFileDescriptor.AutoCloseInputStream(fd);
+ mRemoteOut = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ mContext = context;
+ mListeners = new HashMap<>();
+ }
+
+ /**
+ * Add a listener when a message is received for the message type
+ * @param message Message type
+ * @param listener Execute when a message with the type is received
+ */
+ public void addListener(int message, Listener listener) {
+ mListeners.put(message, listener);
+ }
+
+ public int getAssociationId() {
+ return mAssociationId;
+ }
+
+ protected ParcelFileDescriptor getFd() {
+ return mFd;
}
public abstract void start();
public abstract void stop();
+ protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException;
public Future<byte[]> requestForResponse(int message, byte[] data) {
if (DEBUG) Slog.d(TAG, "Requesting for response");
@@ -99,9 +137,6 @@
return pending;
}
- protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
- throws IOException;
-
protected final void handleMessage(int message, int sequence, @NonNull byte[] data)
throws IOException {
if (DEBUG) {
@@ -130,6 +165,11 @@
sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, data);
break;
}
+ case MESSAGE_REQUEST_PLATFORM_INFO: {
+ callback(message, data);
+ sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);
+ break;
+ }
case MESSAGE_REQUEST_PERMISSION_RESTORE: {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
&& !Build.isDebuggable()) {
@@ -138,7 +178,7 @@
break;
}
try {
- mListener.onRequestPermissionRestore(data);
+ callback(message, data);
sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);
} catch (Exception e) {
Slog.w(TAG, "Failed to restore permissions");
@@ -154,6 +194,12 @@
}
}
+ private void callback(int message, byte[] data) {
+ if (mListeners.containsKey(message)) {
+ mListeners.get(message).onDataReceived(data);
+ }
+ }
+
private void processResponse(int message, int sequence, byte[] data) {
final CompletableFuture<byte[]> future;
synchronized (mPendingRequests) {
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index e52f1d9..1c46028 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -16,7 +16,6 @@
package com.android.server.companion.virtual;
-import static android.companion.virtual.VirtualDeviceParams.RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -29,7 +28,6 @@
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.VirtualDeviceParams.ActivityPolicy;
-import android.companion.virtual.VirtualDeviceParams.RecentsPolicy;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -137,8 +135,8 @@
new ArraySet<>();
@Nullable private final SecureWindowCallback mSecureWindowCallback;
@Nullable private final List<String> mDisplayCategories;
- @RecentsPolicy
- private final int mDefaultRecentsPolicy;
+
+ private final boolean mShowTasksInHostDeviceRecents;
/**
* Creates a window policy controller that is generic to the different use cases of virtual
@@ -166,7 +164,7 @@
* virtual display.
* @param intentListenerCallback Callback that is called to intercept intents when matching
* passed in filters.
- * @param defaultRecentsPolicy a policy to indicate how to handle activities in recents.
+ * @param showTasksInHostDeviceRecents whether to show activities in recents on the host device.
*/
public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
@NonNull ArraySet<UserHandle> allowedUsers,
@@ -181,7 +179,7 @@
@NonNull SecureWindowCallback secureWindowCallback,
@NonNull IntentListenerCallback intentListenerCallback,
@NonNull List<String> displayCategories,
- @RecentsPolicy int defaultRecentsPolicy) {
+ boolean showTasksInHostDeviceRecents) {
super();
mAllowedUsers = allowedUsers;
mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
@@ -196,7 +194,7 @@
mSecureWindowCallback = secureWindowCallback;
mIntentListenerCallback = intentListenerCallback;
mDisplayCategories = displayCategories;
- mDefaultRecentsPolicy = defaultRecentsPolicy;
+ mShowTasksInHostDeviceRecents = showTasksInHostDeviceRecents;
}
/**
@@ -337,7 +335,7 @@
@Override
public boolean canShowTasksInHostDeviceRecents() {
- return (mDefaultRecentsPolicy & RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS) != 0;
+ return mShowTasksInHostDeviceRecents;
}
@Override
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index 21b51b1..607439b 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -88,7 +88,7 @@
*/
private static final int DEVICE_NAME_MAX_LENGTH = 80;
- final Object mLock;
+ final Object mLock = new Object();
/* Token -> file descriptor associations. */
@GuardedBy("mLock")
@@ -101,18 +101,17 @@
private final WindowManager mWindowManager;
private final DeviceCreationThreadVerifier mThreadVerifier;
- InputController(@NonNull Object lock, @NonNull Handler handler,
+ InputController(@NonNull Handler handler,
@NonNull WindowManager windowManager) {
- this(lock, new NativeWrapper(), handler, windowManager,
+ this(new NativeWrapper(), handler, windowManager,
// Verify that virtual devices are not created on the handler thread.
() -> !handler.getLooper().isCurrentThread());
}
@VisibleForTesting
- InputController(@NonNull Object lock, @NonNull NativeWrapper nativeWrapper,
+ InputController(@NonNull NativeWrapper nativeWrapper,
@NonNull Handler handler, @NonNull WindowManager windowManager,
@NonNull DeviceCreationThreadVerifier threadVerifier) {
- mLock = lock;
mHandler = handler;
mNativeWrapper = nativeWrapper;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 642eaef..2d010cf 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -259,7 +259,6 @@
mDisplayManager = displayManager;
if (inputController == null) {
mInputController = new InputController(
- mVirtualDeviceLock,
context.getMainThreadHandler(),
context.getSystemService(WindowManager.class));
} else {
@@ -847,7 +846,9 @@
this::onSecureWindowShown,
this::shouldInterceptIntent,
displayCategories,
- mParams.getDefaultRecentsPolicy());
+ mParams.getDevicePolicy(
+ VirtualDeviceParams.POLICY_TYPE_RECENTS)
+ == VirtualDeviceParams.DEVICE_POLICY_DEFAULT);
gwpc.registerRunningAppsChangedListener(/* listener= */ this);
return gwpc;
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index c8caab9..199fc22 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -74,8 +74,8 @@
"{ ! (diff $(out) $(location :services.core.protolog.json) | grep -q '^<') || " +
"{ echo -e '\\n\\n################################################################\\n#\\n" +
"# ERROR: ProtoLog viewer config is stale. To update it, run:\\n#\\n" +
- "# cp $(location :generate-protolog.json) " +
- "$(location :services.core.protolog.json)\\n#\\n" +
+ "# cp $${ANDROID_BUILD_TOP}/$(location :generate-protolog.json) " +
+ "$${ANDROID_BUILD_TOP}/$(location :services.core.protolog.json)\\n#\\n" +
"################################################################\\n\\n' >&2 && false; } }",
out: ["services.core.protolog.json"],
}
diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java
index 17ef9a2..c6f63dd 100644
--- a/services/core/java/android/os/BatteryStatsInternal.java
+++ b/services/core/java/android/os/BatteryStatsInternal.java
@@ -38,11 +38,13 @@
public static final int CPU_WAKEUP_SUBSYSTEM_UNKNOWN = -1;
public static final int CPU_WAKEUP_SUBSYSTEM_ALARM = 1;
+ public static final int CPU_WAKEUP_SUBSYSTEM_WIFI = 2;
/** @hide */
@IntDef(prefix = {"CPU_WAKEUP_SUBSYSTEM_"}, value = {
CPU_WAKEUP_SUBSYSTEM_UNKNOWN,
CPU_WAKEUP_SUBSYSTEM_ALARM,
+ CPU_WAKEUP_SUBSYSTEM_WIFI,
})
@Retention(RetentionPolicy.SOURCE)
@interface CpuWakeupSubsystem {
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 2992bf9..3ecf933 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -34,7 +34,6 @@
import android.content.IntentFilter;
import android.content.pm.ApexStagedEvent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.Checksum;
import android.content.pm.IBackgroundInstallControlService;
import android.content.pm.IPackageManagerNative;
import android.content.pm.IStagedApexObserver;
@@ -117,14 +116,17 @@
@VisibleForTesting
static final String BINARY_HASH_ERROR = "SHA256HashError";
- static final int MEASURE_APEX_AND_MODULES = 1;
- static final int MEASURE_PRELOADS = 2;
- static final int MEASURE_NEW_MBAS = 3;
-
static final long RECORD_MEASUREMENTS_COOLDOWN_MS = 24 * 60 * 60 * 1000;
static final String APEX_PRELOAD_LOCATION_ERROR = "could-not-be-determined";
+ // Copy from the atom. Consistent for both ApexInfoGathered and MobileBundledAppInfoGathered.
+ static final int DIGEST_ALGORITHM_UNKNOWN = 0;
+ static final int DIGEST_ALGORITHM_CHUNKED_SHA256 = 1;
+ static final int DIGEST_ALGORITHM_CHUNKED_SHA512 = 2;
+ static final int DIGEST_ALGORITHM_VERITY_CHUNKED_SHA256 = 3;
+ static final int DIGEST_ALGORITHM_SHA256 = 4;
+
// used for indicating any type of error during MBA measurement
static final int MBA_STATUS_ERROR = 0;
// used for indicating factory condition preloads
@@ -226,9 +228,9 @@
appInfo.mbaStatus = mbaStatus;
// Only digest and split name are different between splits.
- Checksum checksum = measureApk(split.getPath());
- appInfo.digest = checksum.getValue();
- appInfo.digestAlgorithm = checksum.getType();
+ Digest digest = measureApk(split.getPath());
+ appInfo.digest = digest.value;
+ appInfo.digestAlgorithm = digest.algorithm;
results.add(appInfo);
}
@@ -260,10 +262,9 @@
* Perform basic measurement (i.e. content digest) on a given APK.
*
* @param apkPath The APK (or APEX, since it's also an APK) file to be measured.
- * @return a {@link android.content.pm.Checksum} with preferred digest algorithm type and
- * the checksum.
+ * @return a {@link #Digest} with preferred digest algorithm type and the value.
*/
- private @Nullable Checksum measureApk(@NonNull String apkPath) {
+ private @Nullable Digest measureApk(@NonNull String apkPath) {
// compute content digest
Map<Integer, byte[]> contentDigests = computeApkContentDigest(apkPath);
if (contentDigests == null) {
@@ -274,20 +275,20 @@
// And only one of them will be available per package.
if (contentDigests.containsKey(
ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
+ return new Digest(
+ DIGEST_ALGORITHM_CHUNKED_SHA256,
contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
} else if (contentDigests.containsKey(
ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
+ return new Digest(
+ DIGEST_ALGORITHM_CHUNKED_SHA512,
contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
}
}
// When something went wrong, fall back to simple sha256.
byte[] digest = PackageUtils.computeSha256DigestForLargeFileAsBytes(apkPath,
PackageUtils.createLargeFileBuffer());
- return new Checksum(Checksum.TYPE_WHOLE_SHA256, digest);
+ return new Digest(DIGEST_ALGORITHM_SHA256, digest);
}
@@ -350,7 +351,7 @@
// lastly measure all newly installed MBAs
List<IBinaryTransparencyService.AppInfo> allMbaInfo =
collectAllSilentInstalledMbaInfo(packagesMeasured);
- for (IBinaryTransparencyService.AppInfo appInfo : allUpdatedPreloadInfo) {
+ for (IBinaryTransparencyService.AppInfo appInfo : allMbaInfo) {
packagesMeasured.putBoolean(appInfo.packageName, true);
writeAppInfoToLog(appInfo);
}
@@ -381,7 +382,7 @@
Slog.w(TAG, "Skipping the missing APK in " + pkg.getPath());
continue;
}
- Checksum apexChecksum = measureApk(pkg.getPath());
+ Digest apexChecksum = measureApk(pkg.getPath());
if (apexChecksum == null) {
Slog.w(TAG, "Skipping the missing APEX in " + pkg.getPath());
continue;
@@ -390,8 +391,8 @@
var apexInfo = new IBinaryTransparencyService.ApexInfo();
apexInfo.packageName = packageState.getPackageName();
apexInfo.longVersion = packageState.getVersionCode();
- apexInfo.digest = apexChecksum.getValue();
- apexInfo.digestAlgorithm = apexChecksum.getType();
+ apexInfo.digest = apexChecksum.value;
+ apexInfo.digestAlgorithm = apexChecksum.algorithm;
apexInfo.signerDigests =
computePackageSignerSha256Digests(packageState.getSigningInfo());
@@ -1691,4 +1692,14 @@
}
return slice.getList();
}
+
+ private static class Digest {
+ public int algorithm;
+ public byte[] value;
+
+ Digest(int algorithm, byte[] value) {
+ this.algorithm = algorithm;
+ this.value = value;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 3f1ad3a..2a46d86 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -16,18 +16,12 @@
package com.android.server;
-import static android.content.IntentFilter.BLOCK_NULL_ACTION_INTENTS;
-
-import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
-import android.os.Binder;
-import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.FastImmutableArraySet;
@@ -40,7 +34,6 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.FastPrintWriter;
-import com.android.server.am.ActivityManagerUtils;
import com.android.server.pm.Computer;
import com.android.server.pm.snapshot.PackageDataSnapshot;
@@ -88,7 +81,7 @@
* Returns whether an intent matches the IntentFilter with a pre-resolved type.
*/
public static boolean intentMatchesFilter(
- IntentFilter filter, Intent intent, String resolvedType, boolean blockNullAction) {
+ IntentFilter filter, Intent intent, String resolvedType) {
final boolean debug = localLOGV
|| ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
@@ -102,8 +95,7 @@
}
final int match = filter.match(intent.getAction(), resolvedType, intent.getScheme(),
- intent.getData(), intent.getCategories(), TAG, /* supportWildcards */ false,
- blockNullAction, null, null);
+ intent.getData(), intent.getCategories(), TAG);
if (match >= 0) {
if (debug) {
@@ -358,32 +350,14 @@
return Collections.unmodifiableSet(mFilters);
}
- private boolean blockNullAction(Computer computer, Intent intent,
- String resolvedType, int callingUid, boolean debug) {
- if (intent.getAction() == null) {
- final boolean blockNullAction = UserHandle.isCore(callingUid)
- || computer.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS, callingUid);
- ActivityManagerUtils.logUnsafeIntentEvent(
- UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH,
- callingUid, intent, resolvedType, blockNullAction);
- if (blockNullAction) {
- if (debug) Slog.v(TAG, "Skip matching filters: action is null");
- return true;
- }
- }
- return false;
- }
-
public List<R> queryIntentFromList(@NonNull Computer computer, Intent intent,
- String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut,
- int callingUid, @UserIdInt int userId, long customFlags) {
+ String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut, int userId,
+ long customFlags) {
ArrayList<R> resultList = new ArrayList<R>();
final boolean debug = localLOGV ||
((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
- if (blockNullAction(computer, intent, resolvedType, callingUid, debug)) return resultList;
-
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
final String scheme = intent.getScheme();
int N = listCut.size();
@@ -391,26 +365,18 @@
buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType, scheme,
listCut.get(i), resultList, userId, customFlags);
}
- filterResults(computer, intent, resultList);
+ filterResults(resultList);
sortResults(resultList);
return resultList;
}
- public final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
- String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
- return queryIntent(snapshot, intent, resolvedType, defaultOnly,
- Binder.getCallingUid(), userId, 0);
- }
-
public List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
- String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId) {
- return queryIntent(snapshot, intent, resolvedType, defaultOnly, callingUid, userId, 0);
+ String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+ return queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, 0);
}
protected final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
- String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId,
- long customFlags) {
- final Computer computer = (Computer) snapshot;
+ String resolvedType, boolean defaultOnly, @UserIdInt int userId, long customFlags) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
@@ -422,8 +388,6 @@
TAG, "Resolving type=" + resolvedType + " scheme=" + scheme
+ " defaultOnly=" + defaultOnly + " userId=" + userId + " of " + intent);
- if (blockNullAction(computer, intent, resolvedType, callingUid, debug)) return finalList;
-
F[] firstTypeCut = null;
F[] secondTypeCut = null;
F[] thirdTypeCut = null;
@@ -484,6 +448,7 @@
}
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
+ Computer computer = (Computer) snapshot;
if (firstTypeCut != null) {
buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
scheme, firstTypeCut, finalList, userId, customFlags);
@@ -500,7 +465,7 @@
buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
scheme, schemeCut, finalList, userId, customFlags);
}
- filterResults(computer, intent, finalList);
+ filterResults(finalList);
sortResults(finalList);
if (debug) {
@@ -569,8 +534,7 @@
/**
* Apply filtering to the results. This happens before the results are sorted.
*/
- protected void filterResults(@NonNull Computer computer, @NonNull Intent intent,
- List<R> results) {
+ protected void filterResults(List<R> results) {
}
protected void dumpFilter(PrintWriter out, String prefix, F filter) {
@@ -802,11 +766,7 @@
continue;
}
- match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG,
- false /*supportWildcards*/,
- false /*blockNullAction: already handled*/,
- null /*ignoreActions*/,
- null /*extras*/);
+ match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG);
if (match >= 0) {
if (debug) Slog.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match) + " hasDefault="
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index c5b0f05..c3dda71 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -23,6 +23,18 @@
"file_patterns": ["NotificationManagerService\\.java"]
},
{
+ "name": "CtsScopedStorageCoreHostTest",
+ "file_patterns": ["StorageManagerService\\.java"]
+ },
+ {
+ "name": "CtsScopedStorageHostTest",
+ "file_patterns": ["StorageManagerService\\.java"]
+ },
+ {
+ "name": "CtsScopedStorageDeviceOnlyTest",
+ "file_patterns": ["StorageManagerService\\.java"]
+ },
+ {
"name": "FrameworksMockingServicesTests",
"options": [
{
@@ -63,18 +75,6 @@
],
"presubmit-large": [
{
- "name": "CtsScopedStorageCoreHostTest",
- "file_patterns": ["StorageManagerService\\.java"]
- },
- {
- "name": "CtsScopedStorageHostTest",
- "file_patterns": ["StorageManagerService\\.java"]
- },
- {
- "name": "CtsScopedStorageDeviceOnlyTest",
- "file_patterns": ["StorageManagerService\\.java"]
- },
- {
"name": "CtsContentTestCases",
"options": [
{
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index b352d31..a60f06a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -38,6 +38,7 @@
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -195,6 +196,9 @@
private final IAccountAuthenticatorCache mAuthenticatorCache;
private static final String PRE_N_DATABASE_NAME = "accounts.db";
private static final Intent ACCOUNTS_CHANGED_INTENT;
+ private static final Bundle ACCOUNTS_CHANGED_OPTIONS = new BroadcastOptions()
+ .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+ .toBundle();
private static final int SIGNATURE_CHECK_MISMATCH = 0;
private static final int SIGNATURE_CHECK_MATCH = 1;
@@ -1075,7 +1079,8 @@
Log.i(TAG, "the accountType= " + (accountType == null ? "" : accountType)
+ " changed with useCase=" + useCase + " for userId=" + userId
+ ", sending broadcast of " + ACCOUNTS_CHANGED_INTENT.getAction());
- mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
+ mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId),
+ null /* receiverPermission */, ACCOUNTS_CHANGED_OPTIONS);
}
private void sendAccountRemovedBroadcast(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index c1850bd..f90a3ce 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -137,6 +137,7 @@
import android.app.RemoteServiceException.ForegroundServiceDidNotStartInTimeException;
import android.app.Service;
import android.app.ServiceStartArgs;
+import android.app.StartForegroundCalledOnStoppedServiceException;
import android.app.admin.DevicePolicyEventLogger;
import android.app.compat.CompatChanges;
import android.app.usage.UsageEvents;
@@ -800,13 +801,17 @@
? res.permission : "private to package");
}
-
- // TODO(short-service): This is inside startService() / startForegroundService().
- // Consider if there's anything special we have to do if these are called on an already-
- // running short-FGS... But given these APIs shouldn't change the FGS type, we likely
- // don't need to do anything. (If they would change the FGS type, we'd have to stop
- // the timeout)
ServiceRecord r = res.record;
+ // Note, when startService() or startForegroundService() is called on an already
+ // running SHORT_SERVICE FGS, the call will succeed (i.e. we won't throw
+ // ForegroundServiceStartNotAllowedException), even when the service is alerady timed
+ // out. This is because these APIs will essnetially only change the "started" state
+ // of the service, and it won't afect "the foreground-ness" of the service, or the type
+ // of the FGS.
+ // However, this call will still _not_ extend the SHORT_SERVICE timeout either.
+ // Also, if the app tries to change the type of the FGS later (using
+ // Service.startForeground()), at that point we will consult the BFSL check and the timeout
+ // and make the necessary decisions.
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
backgroundStartPrivileges, false /* isBindService */);
@@ -2035,8 +2040,7 @@
// suddenly disallow it.
// However, this would be very problematic if used with a short-FGS, so we
// explicitly disallow this combination.
- // TODO(short-service): Change to another exception type?
- throw new IllegalStateException(
+ throw new StartForegroundCalledOnStoppedServiceException(
"startForeground(SHORT_SERVICE) called on a service that's not"
+ " started.");
}
@@ -2241,10 +2245,6 @@
cancelForegroundNotificationLocked(r);
r.foregroundId = id;
}
-
- // TODO(short-service): Stop the short service timeout, if the type is changing
- // from short to non-short. (should we do it earlier?)
-
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
r.foregroundNoti = notification;
r.foregroundServiceType = foregroundServiceType;
@@ -3190,7 +3190,7 @@
try {
sr.app.getThread().scheduleTimeoutService(sr, sr.getShortFgsInfo().getStartId());
} catch (RemoteException e) {
- // TODO(short-service): Anything to do here?
+ Slog.w(TAG_SERVICE, "Exception from scheduleTimeoutService: " + e.toString());
}
// Schedule the procstate demotion timeout and ANR timeout.
{
@@ -3262,8 +3262,9 @@
}
mAm.appNotResponding(sr.app, tr);
- // TODO(short-service): Make sure, if the FGS stops after this, the ANR dialog
- // disappears.
+ // TODO: Can we close the ANR dialog here, if it's still shown? Currently, the ANR
+ // dialog really doesn't remember the "cause" (especially if there have been multiple
+ // ANRs), so it's not doable.
}
}
@@ -3278,8 +3279,8 @@
}
}
- // TODO(short-service): Hmm what is it? Should we stop the timeout here?
private void stopServiceAndUpdateAllowlistManagerLocked(ServiceRecord service) {
+ maybeStopShortFgsTimeoutLocked(service);
final ProcessServiceRecord psr = service.app.mServices;
psr.stopService(service);
psr.updateBoundClientUids();
@@ -5406,8 +5407,6 @@
// Check to see if the service had been started as foreground, but being
// brought down before actually showing a notification. That is not allowed.
- // TODO(short-service): This is unlikely related to short-FGS, but I'm curious why it's
- // not allowed. Look into it.
if (r.fgRequired) {
Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
+ r);
@@ -5478,6 +5477,7 @@
cancelForegroundNotificationLocked(r);
final boolean exitingFg = r.isForeground;
if (exitingFg) {
+ maybeStopShortFgsTimeoutLocked(r);
decActiveForegroundAppLocked(smap, r);
synchronized (mAm.mProcessStats.mLock) {
ServiceState stracker = r.getTracker();
@@ -5501,8 +5501,6 @@
mFGSLogger.logForegroundServiceStop(r.appInfo.uid, r);
}
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
-
- // TODO(short-service): Make sure we stop the timeout by here.
}
r.isForeground = false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 9e95e5f..e3f00ded 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -995,7 +995,7 @@
private static final String KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION =
"enable_wait_for_finish_attach_application";
- private static final boolean DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION = false;
+ private static final boolean DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION = true;
/** @see #KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION */
public volatile boolean mEnableWaitForFinishAttachApplication =
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2520fac..ccc218e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -32,7 +32,6 @@
import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -1128,19 +1127,6 @@
}
@Override
- protected void filterResults(@NonNull Computer computer,
- @NonNull Intent intent, List<BroadcastFilter> results) {
- if (intent.getAction() != null) return;
- // When the resolved component is targeting U+, block null action intents
- for (int i = results.size() - 1; i >= 0; --i) {
- if (computer.isChangeEnabled(
- IntentFilter.BLOCK_NULL_ACTION_INTENTS, results.get(i).owningUid)) {
- results.remove(i);
- }
- }
- }
-
- @Override
protected IntentFilter getIntentFilter(@NonNull BroadcastFilter input) {
return input;
}
@@ -3341,7 +3327,6 @@
}
mBatteryStatsService.noteProcessDied(app.info.uid, pid);
- mOomAdjuster.updateShortFgsOwner(app.info.uid, pid, false);
if (!app.isKilled()) {
if (!fromBinderDied) {
@@ -4940,14 +4925,8 @@
EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
synchronized (mProcLock) {
- app.mState.setCurAdj(ProcessList.INVALID_ADJ);
- app.mState.setSetAdj(ProcessList.INVALID_ADJ);
- app.mState.setVerifiedAdj(ProcessList.INVALID_ADJ);
- mOomAdjuster.setAttachingSchedGroupLSP(app);
- app.mState.setForcingToImportant(null);
+ mOomAdjuster.setAttachingProcessStatesLSP(app);
clearProcessForegroundLocked(app);
- app.mState.setHasShownUi(false);
- app.mState.setCached(false);
app.setDebugging(false);
app.setKilledByAm(false);
app.setKilled(false);
@@ -5115,8 +5094,14 @@
app.makeActive(thread, mProcessStats);
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
}
+ app.setPendingFinishAttach(true);
+
updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
+
+ updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
+ checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
+
final long now = SystemClock.uptimeMillis();
synchronized (mAppProfiler.mProfilerLock) {
app.mProfile.setLastRequestedGc(now);
@@ -5132,8 +5117,6 @@
if (!mConstants.mEnableWaitForFinishAttachApplication) {
finishAttachApplicationInner(startSeq, callingUid, pid);
- } else {
- app.setPendingFinishAttach(true);
}
} catch (Exception e) {
// We need kill the process group here. (b/148588589)
@@ -13948,19 +13931,11 @@
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
-
- final boolean blockNullAction = mPlatformCompat.isChangeEnabledInternal(
- IntentFilter.BLOCK_NULL_ACTION_INTENTS, callerApp.info);
// If intent has scheme "content", it will need to access
// provider that needs to lock mProviderMap in ActivityThread
// and also it may need to wait application response, so we
// cannot lock ActivityManagerService here.
- if (filter.match(intent.getAction(), intent.resolveType(resolver),
- intent.getScheme(), intent.getData(), intent.getCategories(), TAG,
- false /* supportWildcards */,
- blockNullAction,
- null /* ignoreActions */,
- intent.getExtras()) >= 0) {
+ if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
@@ -14528,7 +14503,7 @@
brOptions.setDeferUntilActive(true);
}
- if (ordered && brOptions != null && brOptions.isDeferUntilActive()) {
+ if (mEnableModernQueue && ordered && brOptions != null && brOptions.isDeferUntilActive()) {
throw new IllegalArgumentException("Ordered broadcasts can't be deferred until active");
}
@@ -14979,7 +14954,7 @@
}
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(snapshot, intent,
- resolvedType, false /*defaultOnly*/, callingUid, users[i]);
+ resolvedType, false /*defaultOnly*/, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
@@ -14988,7 +14963,7 @@
}
} else {
registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent,
- resolvedType, false /*defaultOnly*/, callingUid, userId);
+ resolvedType, false /*defaultOnly*/, userId);
}
}
BroadcastQueue.traceEnd(cookie);
@@ -18738,23 +18713,6 @@
}
@Override
- public boolean canHoldWakeLocksInDeepDoze(int uid, int procstate) {
- // This method is called with the PowerManager lock held. Do not hold AM here.
-
- // If the procstate is high enough, it's always allowed.
- if (procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- return true;
- }
- // IF it's too low, it's not allowed.
- if (procstate > PROCESS_STATE_IMPORTANT_FOREGROUND) {
- return false;
- }
- // If it's PROCESS_STATE_IMPORTANT_FOREGROUND, then we allow it only wheen the UID
- // has a SHORT_FGS.
- return mOomAdjuster.hasUidShortForegroundService(uid);
- }
-
- @Override
public boolean startProfileEvenWhenDisabled(@UserIdInt int userId) {
return mUserController.startProfile(userId, /* evenWhenDisabled= */ true,
/* unlockListener= */ null);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 34002a9..2c79f8c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -19,7 +19,7 @@
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
@@ -2046,7 +2046,7 @@
int mask = PROCESS_CAPABILITY_FOREGROUND_LOCATION
| PROCESS_CAPABILITY_FOREGROUND_CAMERA
| PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- | PROCESS_CAPABILITY_NETWORK;
+ | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
while ((opt=getNextOption()) != null) {
if (opt.equals("--oom")) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerUtils.java b/services/core/java/com/android/server/am/ActivityManagerUtils.java
index 01466b8..9be553c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerUtils.java
+++ b/services/core/java/com/android/server/am/ActivityManagerUtils.java
@@ -17,13 +17,11 @@
import android.app.ActivityThread;
import android.content.ContentResolver;
-import android.content.Intent;
import android.provider.Settings;
import android.util.ArrayMap;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FrameworkStatsLog;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -135,25 +133,4 @@
public static int hashComponentNameForAtom(String shortInstanceName) {
return getUnsignedHashUnCached(shortInstanceName) ^ getAndroidIdHash();
}
-
- /**
- * Helper method to log an unsafe intent event.
- */
- public static void logUnsafeIntentEvent(int event, int callingUid,
- Intent intent, String resolvedType, boolean blocked) {
- String[] categories = intent.getCategories() == null ? new String[0]
- : intent.getCategories().toArray(String[]::new);
- String component = intent.getComponent() == null ? null
- : intent.getComponent().flattenToString();
- FrameworkStatsLog.write(FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED,
- event,
- callingUid,
- component,
- intent.getPackage(),
- intent.getAction(),
- categories,
- resolvedType,
- intent.getScheme(),
- blocked);
- }
}
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 050ac19..ac2c725 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1892,15 +1892,11 @@
}
long getCpuTimeForPid(int pid) {
- synchronized (mProcessCpuTracker) {
- return mProcessCpuTracker.getCpuTimeForPid(pid);
- }
+ return mProcessCpuTracker.getCpuTimeForPid(pid);
}
long getCpuDelayTimeForPid(int pid) {
- synchronized (mProcessCpuTracker) {
- return mProcessCpuTracker.getCpuDelayTimeForPid(pid);
- }
+ return mProcessCpuTracker.getCpuDelayTimeForPid(pid);
}
List<ProcessCpuTracker.Stats> getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 1607566..0ee883f 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -23,6 +23,7 @@
import static android.Manifest.permission.POWER_SAVER;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
@@ -479,9 +480,29 @@
BatteryStatsService.this.noteJobsDeferred(uid, numDeferred, sinceLast);
}
+ private int transportToSubsystem(NetworkCapabilities nc) {
+ if (nc.hasTransport(TRANSPORT_WIFI)) {
+ return CPU_WAKEUP_SUBSYSTEM_WIFI;
+ }
+ return CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+ }
+
@Override
public void noteCpuWakingNetworkPacket(Network network, long elapsedMillis, int uid) {
- Slog.d(TAG, "Wakeup due to incoming packet on network " + network + " to uid " + uid);
+ if (uid < 0) {
+ Slog.e(TAG, "Invalid uid for waking network packet: " + uid);
+ return;
+ }
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ final NetworkCapabilities nc = cm.getNetworkCapabilities(network);
+ final int subsystem = transportToSubsystem(nc);
+
+ if (subsystem == CPU_WAKEUP_SUBSYSTEM_UNKNOWN) {
+ Slog.wtf(TAG, "Could not map transport for network: " + network
+ + " while attributing wakeup by packet sent to uid: " + uid);
+ return;
+ }
+ noteCpuWakingActivity(subsystem, elapsedMillis, uid);
}
@Override
diff --git a/services/core/java/com/android/server/am/DropboxRateLimiter.java b/services/core/java/com/android/server/am/DropboxRateLimiter.java
index 3792625..9ff2cd0 100644
--- a/services/core/java/com/android/server/am/DropboxRateLimiter.java
+++ b/services/core/java/com/android/server/am/DropboxRateLimiter.java
@@ -31,11 +31,17 @@
// process/eventType) further entries will be rejected until RATE_LIMIT_BUFFER_DURATION has
// elapsed, after which the current count for this breakdown will be reset.
private static final long RATE_LIMIT_BUFFER_DURATION = 10 * DateUtils.MINUTE_IN_MILLIS;
- // The time duration after which the rate limit buffer will be cleared.
- private static final long RATE_LIMIT_BUFFER_EXPIRY = 3 * RATE_LIMIT_BUFFER_DURATION;
+ // Indicated how many buffer durations to wait before the rate limit buffer will be cleared.
+ // E.g. if set to 3 will wait 3xRATE_LIMIT_BUFFER_DURATION before clearing the buffer.
+ private static final long RATE_LIMIT_BUFFER_EXPIRY_FACTOR = 3;
// The number of entries to keep per breakdown of process/eventType.
private static final int RATE_LIMIT_ALLOWED_ENTRIES = 6;
+ // If a process is rate limited twice in a row we consider it crash-looping and rate limit it
+ // more aggressively.
+ private static final int STRICT_RATE_LIMIT_ALLOWED_ENTRIES = 1;
+ private static final long STRICT_RATE_LIMIT_BUFFER_DURATION = 60 * DateUtils.MINUTE_IN_MILLIS;
+
@GuardedBy("mErrorClusterRecords")
private final ArrayMap<String, ErrorRecord> mErrorClusterRecords = new ArrayMap<>();
private final Clock mClock;
@@ -71,15 +77,27 @@
return new RateLimitResult(false, 0);
}
- if (now - errRecord.getStartTime() > RATE_LIMIT_BUFFER_DURATION) {
+ final long timeSinceFirstError = now - errRecord.getStartTime();
+ if (timeSinceFirstError > errRecord.getBufferDuration()) {
final int errCount = recentlyDroppedCount(errRecord);
errRecord.setStartTime(now);
errRecord.setCount(1);
+
+ // If this error happened exactly the next "rate limiting cycle" after the last
+ // error and the previous cycle was rate limiting then increment the successive
+ // rate limiting cycle counter. If a full "cycle" has passed since the last error
+ // then this is no longer a continuous occurrence and will be rate limited normally.
+ if (errCount > 0 && timeSinceFirstError < 2 * errRecord.getBufferDuration()) {
+ errRecord.incrementSuccessiveRateLimitCycles();
+ } else {
+ errRecord.setSuccessiveRateLimitCycles(0);
+ }
+
return new RateLimitResult(false, errCount);
}
errRecord.incrementCount();
- if (errRecord.getCount() > RATE_LIMIT_ALLOWED_ENTRIES) {
+ if (errRecord.getCount() > errRecord.getAllowedEntries()) {
return new RateLimitResult(true, recentlyDroppedCount(errRecord));
}
}
@@ -91,16 +109,19 @@
* dropped. Resets every RATE_LIMIT_BUFFER_DURATION if events are still actively created or
* RATE_LIMIT_BUFFER_EXPIRY if not. */
private int recentlyDroppedCount(ErrorRecord errRecord) {
- if (errRecord == null || errRecord.getCount() < RATE_LIMIT_ALLOWED_ENTRIES) return 0;
- return errRecord.getCount() - RATE_LIMIT_ALLOWED_ENTRIES;
+ if (errRecord == null || errRecord.getCount() < errRecord.getAllowedEntries()) return 0;
+ return errRecord.getCount() - errRecord.getAllowedEntries();
}
- private void maybeRemoveExpiredRecords(long now) {
- if (now - mLastMapCleanUp <= RATE_LIMIT_BUFFER_EXPIRY) return;
+ private void maybeRemoveExpiredRecords(long currentTime) {
+ if (currentTime - mLastMapCleanUp
+ <= RATE_LIMIT_BUFFER_EXPIRY_FACTOR * RATE_LIMIT_BUFFER_DURATION) {
+ return;
+ }
for (int i = mErrorClusterRecords.size() - 1; i >= 0; i--) {
- if (now - mErrorClusterRecords.valueAt(i).getStartTime() > RATE_LIMIT_BUFFER_EXPIRY) {
+ if (mErrorClusterRecords.valueAt(i).hasExpired(currentTime)) {
Counter.logIncrement(
"stability_errors.value_dropbox_buffer_expired_count",
mErrorClusterRecords.valueAt(i).getCount());
@@ -108,7 +129,7 @@
}
}
- mLastMapCleanUp = now;
+ mLastMapCleanUp = currentTime;
}
/** Resets the rate limiter memory. */
@@ -153,10 +174,12 @@
private class ErrorRecord {
long mStartTime;
int mCount;
+ int mSuccessiveRateLimitCycles;
ErrorRecord(long startTime, int count) {
mStartTime = startTime;
mCount = count;
+ mSuccessiveRateLimitCycles = 0;
}
public void setStartTime(long startTime) {
@@ -171,6 +194,14 @@
mCount++;
}
+ public void setSuccessiveRateLimitCycles(int successiveRateLimitCycles) {
+ mSuccessiveRateLimitCycles = successiveRateLimitCycles;
+ }
+
+ public void incrementSuccessiveRateLimitCycles() {
+ mSuccessiveRateLimitCycles++;
+ }
+
public long getStartTime() {
return mStartTime;
}
@@ -178,6 +209,27 @@
public int getCount() {
return mCount;
}
+
+ public int getSuccessiveRateLimitCycles() {
+ return mSuccessiveRateLimitCycles;
+ }
+
+ public boolean isRepeated() {
+ return mSuccessiveRateLimitCycles >= 2;
+ }
+
+ public int getAllowedEntries() {
+ return isRepeated() ? STRICT_RATE_LIMIT_ALLOWED_ENTRIES : RATE_LIMIT_ALLOWED_ENTRIES;
+ }
+
+ public long getBufferDuration() {
+ return isRepeated() ? STRICT_RATE_LIMIT_BUFFER_DURATION : RATE_LIMIT_BUFFER_DURATION;
+ }
+
+ public boolean hasExpired(long currentTime) {
+ long bufferExpiry = RATE_LIMIT_BUFFER_EXPIRY_FACTOR * getBufferDuration();
+ return currentTime - mStartTime > bufferExpiry;
+ }
}
private static class DefaultClock implements Clock {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index d05301a..7121421 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -22,8 +22,8 @@
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
@@ -117,6 +117,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.ServiceInfo;
+import android.net.NetworkPolicyManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManagerInternal;
@@ -127,7 +128,6 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
-import android.util.SparseSetArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.CompositeRWLock;
@@ -367,19 +367,6 @@
@GuardedBy("mService")
private boolean mPendingFullOomAdjUpdate = false;
- /**
- * PIDs that has a SHORT_SERVICE. We need to access it with the PowerManager lock held,
- * so we use a fine-grained lock here.
- */
- @GuardedBy("mPidsWithShortFgs")
- private final ArraySet<Integer> mPidsWithShortFgs = new ArraySet<>();
-
- /**
- * UIDs -> PIDs map, used with mPidsWithShortFgs.
- */
- @GuardedBy("mPidsWithShortFgs")
- private final SparseSetArray<Integer> mUidsToPidsWithShortFgs = new SparseSetArray<>();
-
/** Overrideable by a test */
@VisibleForTesting
protected boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -1273,12 +1260,19 @@
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
final ProcessStateRecord state = app.mState;
- if (!app.isKilledByAm() && app.getThread() != null && !app.isPendingFinishAttach()) {
+ if (!app.isKilledByAm() && app.getThread() != null) {
// We don't need to apply the update for the process which didn't get computed
if (state.getCompletedAdjSeq() == mAdjSeq) {
applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason);
}
+ if (app.isPendingFinishAttach()) {
+ // Avoid trimming processes that are still initializing. If they aren't
+ // hosting any components yet because they may be unfairly killed.
+ // We however apply any computed previously computed oom scores before skipping.
+ continue;
+ }
+
final ProcessServiceRecord psr = app.mServices;
// Count the number of process types.
switch (state.getCurProcState()) {
@@ -1712,6 +1706,19 @@
return false;
}
+ if (app.isPendingFinishAttach()) {
+ state.setAdjSeq(mAdjSeq);
+ state.setCompletedAdjSeq(mAdjSeq);
+ // If the process is still initializing, we skip computing any states because we
+ // don't want to override the special states that have been set at
+ // AMS#attachApplication with OomAdjuster#setAttachingProcessStates.
+ // In this limbo state, the app has |PROC_START_TIMEOUT| to finish attach application
+ // and receive updated proc_state based on its importance.
+ // Note that in this state, the oom_score is INVALID_ADJ which is outside the standard
+ // oom score range and the app is safe from lmkd kills.
+ return false;
+ }
+
state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
state.setAdjSource(null);
state.setAdjTarget(null);
@@ -1956,7 +1963,6 @@
}
}
}
- updateShortFgsOwner(psr.mApp.uid, psr.mApp.mPid, hasShortForegroundServices);
// If the app was recently in the foreground and moved to a foreground service status,
// allow it to get a higher rank in memory for some time, compared to other foreground
@@ -2185,8 +2191,6 @@
}
}
- // TODO(short-service): While-in-user permissions. Do we need any change here for
- // short-FGS? (Likely not)
if (s.isForeground) {
final int fgsType = s.foregroundServiceType;
if (s.mAllowWhileInUsePermissionInFgs) {
@@ -2277,14 +2281,15 @@
// elevated to a high enough procstate anyway to get network unless they
// request otherwise, so don't propagate the network capability by default
// in this case unless they explicitly request it.
- if ((cstate.getCurCapability() & PROCESS_CAPABILITY_NETWORK) != 0) {
+ if ((cstate.getCurCapability()
+ & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0) {
if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
// This is used to grant network access to Expedited Jobs.
if (cr.hasFlag(Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)) {
- capability |= PROCESS_CAPABILITY_NETWORK;
+ capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
}
} else {
- capability |= PROCESS_CAPABILITY_NETWORK;
+ capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
}
}
@@ -2795,27 +2800,33 @@
}
private int getDefaultCapability(ProcessRecord app, int procState) {
+ final int networkCapabilities =
+ NetworkPolicyManager.getDefaultProcessNetworkCapabilities(procState);
+ final int baseCapabilities;
switch (procState) {
case PROCESS_STATE_PERSISTENT:
case PROCESS_STATE_PERSISTENT_UI:
case PROCESS_STATE_TOP:
- return PROCESS_CAPABILITY_ALL; // BFSL allowed
+ baseCapabilities = PROCESS_CAPABILITY_ALL; // BFSL allowed
+ break;
case PROCESS_STATE_BOUND_TOP:
- return PROCESS_CAPABILITY_NETWORK | PROCESS_CAPABILITY_BFSL;
+ baseCapabilities = PROCESS_CAPABILITY_BFSL;
+ break;
case PROCESS_STATE_FOREGROUND_SERVICE:
if (app.getActiveInstrumentation() != null) {
- return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK ;
+ baseCapabilities = PROCESS_CAPABILITY_ALL_IMPLICIT;
} else {
// Capability from foreground service is conditional depending on
// foregroundServiceType in the manifest file and the
// mAllowWhileInUsePermissionInFgs flag.
- return PROCESS_CAPABILITY_NETWORK;
+ baseCapabilities = PROCESS_CAPABILITY_NONE;
}
- case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
- return PROCESS_CAPABILITY_NETWORK;
+ break;
default:
- return PROCESS_CAPABILITY_NONE;
+ baseCapabilities = PROCESS_CAPABILITY_NONE;
+ break;
}
+ return baseCapabilities | networkCapabilities;
}
/**
@@ -3228,7 +3239,7 @@
}
@GuardedBy({"mService", "mProcLock"})
- void setAttachingSchedGroupLSP(ProcessRecord app) {
+ void setAttachingProcessStatesLSP(ProcessRecord app) {
int initialSchedGroup = SCHED_GROUP_DEFAULT;
final ProcessStateRecord state = app.mState;
// If the process has been marked as foreground, it is starting as the top app (with
@@ -3248,6 +3259,15 @@
state.setSetSchedGroup(initialSchedGroup);
state.setCurrentSchedulingGroup(initialSchedGroup);
+ state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
+ state.setCurCapability(PROCESS_CAPABILITY_NONE);
+
+ state.setCurAdj(ProcessList.FOREGROUND_APP_ADJ);
+ state.setSetAdj(ProcessList.FOREGROUND_APP_ADJ);
+ state.setVerifiedAdj(ProcessList.FOREGROUND_APP_ADJ);
+ state.setForcingToImportant(null);
+ state.setHasShownUi(false);
+ state.setCached(true);
}
// ONLY used for unit testing in OomAdjusterTests.java
@@ -3468,40 +3488,4 @@
mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
}
}
-
- /**
- * Update {@link #mPidsWithShortFgs} and {@link #mUidsToPidsWithShortFgs} to keep track
- * of which UID/PID has a short FGS.
- *
- * TODO(short-FGS): Remove it and all the relevant code once SHORT_FGS use the FGS procstate.
- */
- void updateShortFgsOwner(int uid, int pid, boolean add) {
- synchronized (mPidsWithShortFgs) {
- if (add) {
- mUidsToPidsWithShortFgs.add(uid, pid);
- mPidsWithShortFgs.add(pid);
- } else {
- mUidsToPidsWithShortFgs.remove(uid, pid);
- mPidsWithShortFgs.remove(pid);
- }
- }
- }
-
- /**
- * Whether a UID has a (non-timed-out) short FGS or not.
- * It's indirectly called by PowerManager, so we can't hold the AM lock in it.
- */
- boolean hasUidShortForegroundService(int uid) {
- synchronized (mPidsWithShortFgs) {
- final ArraySet<Integer> pids = mUidsToPidsWithShortFgs.get(uid);
- if (pids == null || pids.size() == 0) {
- return false;
- }
- for (int i = pids.size() - 1; i >= 0; i--) {
- final int pid = pids.valueAt(i);
- return mPidsWithShortFgs.contains(pid);
- }
- }
- return false;
- }
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f4e2b0f..35f71f7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3100,9 +3100,10 @@
hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
final ProcessStateRecord state = r.mState;
- if (!mService.mBooted && !mService.mBooting
+ if (!isolated && !isSdkSandbox
&& userId == UserHandle.USER_SYSTEM
- && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+ && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK
+ && (TextUtils.equals(proc, info.processName))) {
// The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
state.setSetSchedGroup(ProcessList.SCHED_GROUP_DEFAULT);
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index c6a8bcd..d4bcd9e 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -106,9 +106,7 @@
{ "exclude-annotation": "androidx.test.filters.FlakyTest" },
{ "exclude-annotation": "org.junit.Ignore" }
]
- }
- ],
- "presubmit-large": [
+ },
{
"name": "CtsUsageStatsTestCases",
"file_patterns": [
diff --git a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
index 49279d4..2d6966a 100644
--- a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
@@ -327,9 +327,12 @@
}
private void commitUidPendingState(int uid) {
- int pendingUidState = mPendingUidStates.get(uid, MIN_PRIORITY_UID_STATE);
- int pendingCapability = mPendingCapability.get(uid, PROCESS_CAPABILITY_NONE);
- boolean pendingVisibleAppWidget = mPendingVisibleAppWidget.get(uid, false);
+ int pendingUidState = mPendingUidStates.get(uid,
+ mUidStates.get(uid, MIN_PRIORITY_UID_STATE));
+ int pendingCapability = mPendingCapability.get(uid,
+ mCapability.get(uid, PROCESS_CAPABILITY_NONE));
+ boolean pendingVisibleAppWidget = mPendingVisibleAppWidget.get(uid,
+ mVisibleAppWidget.get(uid, false));
int uidState = mUidStates.get(uid, MIN_PRIORITY_UID_STATE);
int capability = mCapability.get(uid, PROCESS_CAPABILITY_NONE);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0d0e576..1f24eb3 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3928,8 +3928,10 @@
}
@Override
- @android.annotation.EnforcePermission(anyOf =
- {"MODIFY_AUDIO_ROUTING", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+ @android.annotation.EnforcePermission(anyOf = {
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+ android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+ })
/** @see AudioDeviceVolumeManager#setDeviceVolume(VolumeInfo, AudioDeviceAttributes)
* Part of service interface, check permissions and parameters here
* Note calling package is for logging purposes only, not to be trusted
@@ -4945,8 +4947,10 @@
}
@Override
- @android.annotation.EnforcePermission(anyOf =
- {"MODIFY_AUDIO_ROUTING", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+ @android.annotation.EnforcePermission(anyOf = {
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+ android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+ })
/**
* @see AudioDeviceVolumeManager#getDeviceVolume(VolumeInfo, AudioDeviceAttributes)
*/
@@ -7214,8 +7218,10 @@
* @param device the audio device to be affected
* @param deviceVolumeBehavior one of the device behaviors
*/
- @android.annotation.EnforcePermission(anyOf =
- {"MODIFY_AUDIO_ROUTING", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+ @android.annotation.EnforcePermission(anyOf = {
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+ android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+ })
public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device,
@AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior, @Nullable String pkgName) {
// verify permissions
@@ -7295,8 +7301,11 @@
* @param device the audio output device type
* @return the volume behavior for the device
*/
- @android.annotation.EnforcePermission(anyOf =
- {"MODIFY_AUDIO_ROUTING", "QUERY_AUDIO_STATE", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+ @android.annotation.EnforcePermission(anyOf = {
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+ android.Manifest.permission.QUERY_AUDIO_STATE,
+ android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+ })
public @AudioManager.DeviceVolumeBehavior
int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) {
// verify permissions
diff --git a/services/core/java/com/android/server/audio/TEST_MAPPING b/services/core/java/com/android/server/audio/TEST_MAPPING
index 300a2c8..2cea32a 100644
--- a/services/core/java/com/android/server/audio/TEST_MAPPING
+++ b/services/core/java/com/android/server/audio/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit-large": [
+ "presubmit": [
{
"name": "CtsMediaAudioTestCases",
"options": [
@@ -24,9 +24,7 @@
"include-annotation": "android.platform.test.annotations.Presubmit"
}
]
- }
- ],
- "presubmit": [
+ },
{
"name": "FrameworksServicesTests",
"options": [
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
index 7b8f824..f516a49 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
@@ -37,6 +37,7 @@
private static final String TAG = "BiometricNotificationUtils";
private static final String RE_ENROLL_NOTIFICATION_TAG = "FaceService";
private static final String BAD_CALIBRATION_NOTIFICATION_TAG = "FingerprintService";
+ private static final String KEY_RE_ENROLL_FACE = "re_enroll_face_unlock";
private static final int NOTIFICATION_ID = 1;
private static final long NOTIFICATION_INTERVAL_MS = 24 * 60 * 60 * 1000;
private static long sLastAlertTime = 0;
@@ -57,6 +58,7 @@
final Intent intent = new Intent("android.settings.FACE_SETTINGS");
intent.setPackage("com.android.settings");
+ intent.putExtra(KEY_RE_ENROLL_FACE, true);
final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context,
0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */,
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 6d7b2cb..c2994a9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -260,9 +260,8 @@
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
return -1;
- } else {
- options.setSensorId(provider.first);
}
+ options.setSensorId(provider.first);
return provider.second.scheduleAuthenticate(token, operationId,
0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
@@ -286,6 +285,7 @@
Slog.w(TAG, "Null provider for detectFace");
return -1;
}
+ options.setSensorId(provider.first);
return provider.second.scheduleFaceDetect(token,
new ClientMonitorCallbackConverter(receiver), options,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index f6c1375..dc00ffc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -261,7 +261,6 @@
final String opPackageName = options.getOpPackageName();
final String attributionTag = options.getAttributionTag();
final int userId = options.getUserId();
- final int sensorId = options.getSensorId();
if (!canUseFingerprint(
opPackageName,
@@ -298,21 +297,22 @@
: BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;
final Pair<Integer, ServiceProvider> provider;
- if (sensorId == FingerprintManager.SENSOR_ID_ANY) {
+ if (options.getSensorId() == FingerprintManager.SENSOR_ID_ANY) {
provider = mRegistry.getSingleProvider();
} else {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- provider = new Pair<>(sensorId, mRegistry.getProviderForSensor(sensorId));
+ provider = new Pair<>(options.getSensorId(),
+ mRegistry.getProviderForSensor(options.getSensorId()));
}
+
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
return -1;
- } else {
- options.setSensorId(provider.first);
}
+ options.setSensorId(provider.first);
final FingerprintSensorPropertiesInternal sensorProps =
- provider.second.getSensorProperties(sensorId);
+ provider.second.getSensorProperties(options.getSensorId());
if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName)
&& sensorProps != null && sensorProps.isAnyUdfpsType()) {
try {
@@ -431,9 +431,8 @@
if (provider == null) {
Slog.w(TAG, "Null provider for detectFingerprint");
return -1;
- } else {
- options.setSensorId(provider.first);
}
+ options.setSensorId(provider.first);
return provider.second.scheduleFingerDetect(token,
new ClientMonitorCallbackConverter(receiver), options,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
index 1630be7..bae84bd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
@@ -48,6 +48,8 @@
return BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR;
} else if (aidlError == Error.BAD_CALIBRATION) {
return BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION;
+ } else if (aidlError == Error.POWER_PRESS) {
+ return BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED;
} else {
return BiometricFingerprintConstants.FINGERPRINT_ERROR_UNKNOWN;
}
@@ -84,6 +86,8 @@
} else if (aidlAcquiredInfo == AcquiredInfo.RETRYING_CAPTURE) {
// No framework constant available
return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
+ } else if (aidlAcquiredInfo == AcquiredInfo.POWER_PRESS) {
+ return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED;
} else {
return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 513b3e3..c2ca78e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -274,8 +274,5 @@
}
@Override
- public void onPowerPressed() {
- onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED,
- 0 /* vendorCode */);
- }
+ public void onPowerPressed() {}
}
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 3a4aaa7..1f82961 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -31,7 +31,9 @@
import android.net.metrics.NetworkMetrics;
import android.net.metrics.WakeupEvent;
import android.net.metrics.WakeupStats;
+import android.os.BatteryStatsInternal;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -44,6 +46,7 @@
import com.android.internal.util.RingBuffer;
import com.android.internal.util.TokenBucket;
import com.android.net.module.util.BaseNetdEventListener;
+import com.android.server.LocalServices;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
import java.io.PrintWriter;
@@ -74,7 +77,7 @@
// TODO: dedup this String constant with the one used in
// ConnectivityService#wakeupModifyInterface().
@VisibleForTesting
- static final String WAKEUP_EVENT_IFACE_PREFIX = "iface:";
+ static final String WAKEUP_EVENT_PREFIX_DELIM = ":";
// Array of aggregated DNS and connect events sent by netd, grouped by net id.
@GuardedBy("this")
@@ -278,17 +281,14 @@
@Override
public synchronized void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader,
byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs) {
- String iface = prefix.replaceFirst(WAKEUP_EVENT_IFACE_PREFIX, "");
- final long timestampMs;
- if (timestampNs > 0) {
- timestampMs = timestampNs / NANOS_PER_MS;
- } else {
- timestampMs = System.currentTimeMillis();
+ final String[] prefixParts = prefix.split(WAKEUP_EVENT_PREFIX_DELIM);
+ if (prefixParts.length != 2) {
+ throw new IllegalArgumentException("Prefix " + prefix
+ + " required in format <nethandle>:<interface>");
}
- WakeupEvent event = new WakeupEvent();
- event.iface = iface;
- event.timestampMs = timestampMs;
+ final WakeupEvent event = new WakeupEvent();
+ event.iface = prefixParts[1];
event.uid = uid;
event.ethertype = ethertype;
event.dstHwAddr = MacAddress.fromBytes(dstHw);
@@ -297,11 +297,25 @@
event.ipNextHeader = ipNextHeader;
event.srcPort = srcPort;
event.dstPort = dstPort;
+ if (timestampNs > 0) {
+ event.timestampMs = timestampNs / NANOS_PER_MS;
+ } else {
+ event.timestampMs = System.currentTimeMillis();
+ }
addWakeupEvent(event);
- String dstMac = event.dstHwAddr.toString();
+ final BatteryStatsInternal bsi = LocalServices.getService(BatteryStatsInternal.class);
+ if (bsi != null) {
+ final long netHandle = Long.parseLong(prefixParts[0]);
+ final long elapsedMs = SystemClock.elapsedRealtime() + event.timestampMs
+ - System.currentTimeMillis();
+ bsi.noteCpuWakingNetworkPacket(Network.fromNetworkHandle(netHandle), elapsedMs,
+ event.uid);
+ }
+
+ final String dstMac = event.dstHwAddr.toString();
FrameworkStatsLog.write(FrameworkStatsLog.PACKET_WAKEUP_OCCURRED,
- uid, iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
+ uid, event.iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
}
@Override
diff --git a/services/core/java/com/android/server/cpu/CpuInfoReader.java b/services/core/java/com/android/server/cpu/CpuInfoReader.java
index ca97a98..ce68edbb 100644
--- a/services/core/java/com/android/server/cpu/CpuInfoReader.java
+++ b/services/core/java/com/android/server/cpu/CpuInfoReader.java
@@ -21,8 +21,10 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.os.SystemClock;
import android.system.Os;
import android.system.OsConstants;
+import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.LongSparseLongArray;
import android.util.SparseArray;
@@ -50,6 +52,9 @@
private static final String POLICY_DIR_PREFIX = "policy";
private static final String RELATED_CPUS_FILE = "related_cpus";
private static final String AFFECTED_CPUS_FILE = "affected_cpus";
+ // TODO(b/263154344): Avoid reading from cpuinfo_cur_freq because non-root users don't have
+ // read permission for this file. The file permissions are set by the Kernel. Instead, read
+ // the current frequency only from scaling_cur_freq.
private static final String CUR_CPUFREQ_FILE = "cpuinfo_cur_freq";
private static final String MAX_CPUFREQ_FILE = "cpuinfo_max_freq";
private static final String CUR_SCALING_FREQ_FILE = "scaling_cur_freq";
@@ -70,16 +75,18 @@
private static final Pattern TIME_IN_STATE_PATTERN =
Pattern.compile("(?<freqKHz>[0-9]+)\\s(?<time>[0-9]+)");
private static final long MILLIS_PER_CLOCK_TICK = 1000L / Os.sysconf(OsConstants._SC_CLK_TCK);
+ private static final long MIN_READ_INTERVAL_MILLISECONDS = 500;
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"FLAG_CPUSET_CATEGORY_"}, flag = true, value = {
FLAG_CPUSET_CATEGORY_TOP_APP,
FLAG_CPUSET_CATEGORY_BACKGROUND
})
- private @interface CpusetCategory{}
+ /** package **/ @interface CpusetCategory{}
// TODO(b/242722241): Protect updatable variables with a local lock.
private final File mCpusetDir;
+ private final long mMinReadIntervalMillis;
private final SparseIntArray mCpusetCategoriesByCpus = new SparseIntArray();
private final SparseArray<File> mCpuFreqPolicyDirsById = new SparseArray<>();
private final SparseArray<StaticPolicyInfo> mStaticPolicyInfoById = new SparseArray<>();
@@ -90,16 +97,20 @@
private SparseArray<CpuUsageStats> mCumulativeCpuUsageStats = new SparseArray<>();
private boolean mIsEnabled;
private boolean mHasTimeInStateFile;
+ private long mLastReadUptimeMillis;
+ private SparseArray<CpuInfo> mLastReadCpuInfos;
public CpuInfoReader() {
- this(new File(CPUSET_DIR_PATH), new File(CPUFREQ_DIR_PATH), new File(PROC_STAT_FILE_PATH));
+ this(new File(CPUSET_DIR_PATH), new File(CPUFREQ_DIR_PATH), new File(PROC_STAT_FILE_PATH),
+ MIN_READ_INTERVAL_MILLISECONDS);
}
@VisibleForTesting
- CpuInfoReader(File cpusetDir, File cpuFreqDir, File procStatFile) {
+ CpuInfoReader(File cpusetDir, File cpuFreqDir, File procStatFile, long minReadIntervalMillis) {
mCpusetDir = cpusetDir;
mCpuFreqDir = cpuFreqDir;
mProcStatFile = procStatFile;
+ mMinReadIntervalMillis = minReadIntervalMillis;
}
/**
@@ -167,6 +178,16 @@
if (!mIsEnabled) {
return null;
}
+ long uptimeMillis = SystemClock.uptimeMillis();
+ if (mLastReadUptimeMillis > 0
+ && uptimeMillis - mLastReadUptimeMillis < mMinReadIntervalMillis) {
+ Slogf.w(TAG, "Skipping reading from device and returning the last read CpuInfos. "
+ + "Last read was %d ms ago, min read interval is %d ms",
+ uptimeMillis - mLastReadUptimeMillis, mMinReadIntervalMillis);
+ return mLastReadCpuInfos;
+ }
+ mLastReadUptimeMillis = uptimeMillis;
+ mLastReadCpuInfos = null;
SparseArray<CpuUsageStats> cpuUsageStatsByCpus = readLatestCpuUsageStats();
if (cpuUsageStatsByCpus == null || cpuUsageStatsByCpus.size() == 0) {
Slogf.e(TAG, "Failed to read latest CPU usage stats");
@@ -202,6 +223,12 @@
+ " policy ID %d", policyId);
continue;
}
+ if (curFreqKHz > maxFreqKHz) {
+ Slogf.w(TAG, "Current CPU frequency (%d) is greater than maximum CPU frequency"
+ + " (%d) for policy ID (%d). Skipping CPU frequency policy", curFreqKHz,
+ maxFreqKHz, policyId);
+ continue;
+ }
for (int coreIdx = 0; coreIdx < staticPolicyInfo.relatedCpuCores.size(); coreIdx++) {
int relatedCpuCore = staticPolicyInfo.relatedCpuCores.get(coreIdx);
CpuInfo prevCpuInfo = cpuInfoByCpus.get(relatedCpuCore);
@@ -241,9 +268,73 @@
}
}
}
+ mLastReadCpuInfos = cpuInfoByCpus;
return cpuInfoByCpus;
}
+ /** Dumps the current state. */
+ public void dump(IndentingPrintWriter writer) {
+ writer.printf("*%s*\n", getClass().getSimpleName());
+ writer.increaseIndent(); // Add intend for the outermost block.
+
+ writer.printf("mCpusetDir = %s\n", mCpusetDir.getAbsolutePath());
+ writer.printf("mCpuFreqDir = %s\n", mCpuFreqDir.getAbsolutePath());
+ writer.printf("mProcStatFile = %s\n", mProcStatFile.getAbsolutePath());
+ writer.printf("mIsEnabled = %s\n", mIsEnabled);
+ writer.printf("mHasTimeInStateFile = %s\n", mHasTimeInStateFile);
+ writer.printf("mLastReadUptimeMillis = %d\n", mLastReadUptimeMillis);
+ writer.printf("mMinReadIntervalMillis = %d\n", mMinReadIntervalMillis);
+
+ writer.printf("Cpuset categories by CPU core:\n");
+ writer.increaseIndent();
+ for (int i = 0; i < mCpusetCategoriesByCpus.size(); i++) {
+ writer.printf("CPU core id = %d, %s\n", mCpusetCategoriesByCpus.keyAt(i),
+ toCpusetCategoriesStr(mCpusetCategoriesByCpus.valueAt(i)));
+ }
+ writer.decreaseIndent();
+
+ writer.println("Cpu frequency policy directories by policy id:");
+ writer.increaseIndent();
+ for (int i = 0; i < mCpuFreqPolicyDirsById.size(); i++) {
+ writer.printf("Policy id = %d, Dir = %s\n", mCpuFreqPolicyDirsById.keyAt(i),
+ mCpuFreqPolicyDirsById.valueAt(i));
+ }
+ writer.decreaseIndent();
+
+ writer.println("Static cpu frequency policy infos by policy id:");
+ writer.increaseIndent();
+ for (int i = 0; i < mStaticPolicyInfoById.size(); i++) {
+ writer.printf("Policy id = %d, %s\n", mStaticPolicyInfoById.keyAt(i),
+ mStaticPolicyInfoById.valueAt(i));
+ }
+ writer.decreaseIndent();
+
+ writer.println("Cpu time in frequency state by policy id:");
+ writer.increaseIndent();
+ for (int i = 0; i < mTimeInStateByPolicyId.size(); i++) {
+ writer.printf("Policy id = %d, Time(millis) in state by CPU frequency(KHz) = %s\n",
+ mTimeInStateByPolicyId.keyAt(i), mTimeInStateByPolicyId.valueAt(i));
+ }
+ writer.decreaseIndent();
+
+ writer.println("Last read CPU infos:");
+ writer.increaseIndent();
+ for (int i = 0; i < mLastReadCpuInfos.size(); i++) {
+ writer.printf("%s\n", mLastReadCpuInfos.valueAt(i));
+ }
+ writer.decreaseIndent();
+
+ writer.println("Latest cumulative CPU usage stats by CPU core:");
+ writer.increaseIndent();
+ for (int i = 0; i < mCumulativeCpuUsageStats.size(); i++) {
+ writer.printf("CPU core id = %d, %s\n", mCumulativeCpuUsageStats.keyAt(i),
+ mCumulativeCpuUsageStats.valueAt(i));
+ }
+ writer.decreaseIndent();
+
+ writer.decreaseIndent(); // Remove intend for the outermost block.
+ }
+
/**
* Sets the CPU frequency for testing.
*
@@ -496,6 +587,9 @@
for (int i = 0; i < timeInState.size(); i++) {
totalTimeInState += timeInState.valueAt(i);
}
+ if (totalTimeInState == 0) {
+ return CpuInfo.MISSING_FREQUENCY;
+ }
double avgFreqKHz = 0;
for (int i = 0; i < timeInState.size(); i++) {
avgFreqKHz += (timeInState.keyAt(i) * timeInState.valueAt(i)) / totalTimeInState;
@@ -624,16 +718,29 @@
@CpusetCategory
public final int cpusetCategories;
public final boolean isOnline;
+ public final long maxCpuFreqKHz;
// Values in the below fields may be missing when a CPU core is offline.
public final long curCpuFreqKHz;
- public final long maxCpuFreqKHz;
public final long avgTimeInStateCpuFreqKHz;
@Nullable
public final CpuUsageStats latestCpuUsageStats;
+ private long mNormalizedAvailableCpuFreqKHz;
+
CpuInfo(int cpuCore, @CpusetCategory int cpusetCategories, boolean isOnline,
long curCpuFreqKHz, long maxCpuFreqKHz, long avgTimeInStateCpuFreqKHz,
CpuUsageStats latestCpuUsageStats) {
+ this(cpuCore, cpusetCategories, isOnline, curCpuFreqKHz, maxCpuFreqKHz,
+ avgTimeInStateCpuFreqKHz, /* normalizedAvailableCpuFreqKHz= */ 0,
+ latestCpuUsageStats);
+ this.mNormalizedAvailableCpuFreqKHz = computeNormalizedAvailableCpuFreqKHz();
+ }
+
+ // Should be used only for testing.
+ @VisibleForTesting
+ CpuInfo(int cpuCore, @CpusetCategory int cpusetCategories, boolean isOnline,
+ long curCpuFreqKHz, long maxCpuFreqKHz, long avgTimeInStateCpuFreqKHz,
+ long normalizedAvailableCpuFreqKHz, CpuUsageStats latestCpuUsageStats) {
this.cpuCore = cpuCore;
this.cpusetCategories = cpusetCategories;
this.isOnline = isOnline;
@@ -641,6 +748,11 @@
this.maxCpuFreqKHz = maxCpuFreqKHz;
this.avgTimeInStateCpuFreqKHz = avgTimeInStateCpuFreqKHz;
this.latestCpuUsageStats = latestCpuUsageStats;
+ this.mNormalizedAvailableCpuFreqKHz = normalizedAvailableCpuFreqKHz;
+ }
+
+ public long getNormalizedAvailableCpuFreqKHz() {
+ return mNormalizedAvailableCpuFreqKHz;
}
@Override
@@ -657,6 +769,8 @@
.append(avgTimeInStateCpuFreqKHz == MISSING_FREQUENCY ? "missing"
: avgTimeInStateCpuFreqKHz)
.append(", latestCpuUsageStats = ").append(latestCpuUsageStats)
+ .append(", mNormalizedAvailableCpuFreqKHz = ")
+ .append(mNormalizedAvailableCpuFreqKHz)
.append(" }").toString();
}
@@ -673,13 +787,32 @@
&& isOnline == other.isOnline && curCpuFreqKHz == other.curCpuFreqKHz
&& maxCpuFreqKHz == other.maxCpuFreqKHz
&& avgTimeInStateCpuFreqKHz == other.avgTimeInStateCpuFreqKHz
- && latestCpuUsageStats.equals(other.latestCpuUsageStats);
+ && latestCpuUsageStats.equals(other.latestCpuUsageStats)
+ && mNormalizedAvailableCpuFreqKHz == other.mNormalizedAvailableCpuFreqKHz;
}
@Override
public int hashCode() {
return Objects.hash(cpuCore, cpusetCategories, isOnline, curCpuFreqKHz, maxCpuFreqKHz,
- avgTimeInStateCpuFreqKHz, latestCpuUsageStats);
+ avgTimeInStateCpuFreqKHz, latestCpuUsageStats, mNormalizedAvailableCpuFreqKHz);
+ }
+
+ private long computeNormalizedAvailableCpuFreqKHz() {
+ if (!isOnline) {
+ return MISSING_FREQUENCY;
+ }
+ long totalTimeMillis = latestCpuUsageStats.getTotalTimeMillis();
+ if (totalTimeMillis == 0) {
+ Slogf.wtf(TAG, "Total CPU time millis is 0. This shouldn't happen unless stats are"
+ + " polled too frequently");
+ return MISSING_FREQUENCY;
+ }
+ double nonIdlePercent = 100.0 * (totalTimeMillis
+ - (double) latestCpuUsageStats.idleTimeMillis) / totalTimeMillis;
+ long curFreqKHz = avgTimeInStateCpuFreqKHz == MISSING_FREQUENCY
+ ? curCpuFreqKHz : avgTimeInStateCpuFreqKHz;
+ double availablePercent = 100.0 - (nonIdlePercent * curFreqKHz / maxCpuFreqKHz);
+ return (long) ((availablePercent * maxCpuFreqKHz) / 100.0);
}
}
@@ -712,7 +845,7 @@
this.guestNiceTimeMillis = guestNiceTimeMillis;
}
- public long getTotalTime() {
+ public long getTotalTimeMillis() {
return userTimeMillis + niceTimeMillis + systemTimeMillis + idleTimeMillis
+ iowaitTimeMillis + irqTimeMillis + softirqTimeMillis + stealTimeMillis
+ guestTimeMillis + guestNiceTimeMillis;
@@ -796,8 +929,8 @@
@Override
public String toString() {
- return "FrequencyPair{cpuFreqKHz=" + cpuFreqKHz + ", scalingFreqKHz=" + scalingFreqKHz
- + '}';
+ return "FrequencyPair{cpuFreqKHz = " + cpuFreqKHz + ", scalingFreqKHz = "
+ + scalingFreqKHz + '}';
}
}
@@ -812,7 +945,7 @@
@Override
public String toString() {
- return "StaticPolicyInfo{maxCpuFreqPair=" + maxCpuFreqPair + ", relatedCpuCores="
+ return "StaticPolicyInfo{maxCpuFreqPair = " + maxCpuFreqPair + ", relatedCpuCores = "
+ relatedCpuCores + '}';
}
}
@@ -831,9 +964,9 @@
@Override
public String toString() {
- return "DynamicPolicyInfo{curCpuFreqPair=" + curCpuFreqPair
- + ", avgTimeInStateCpuFreqKHz=" + avgTimeInStateCpuFreqKHz
- + ", affectedCpuCores=" + affectedCpuCores + '}';
+ return "DynamicPolicyInfo{curCpuFreqPair = " + curCpuFreqPair
+ + ", avgTimeInStateCpuFreqKHz = " + avgTimeInStateCpuFreqKHz
+ + ", affectedCpuCores = " + affectedCpuCores + '}';
}
}
}
diff --git a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
index ce29013..63218ee 100644
--- a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
+++ b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
@@ -138,6 +138,8 @@
display.setPosition(POSITION_UNKNOWN);
}
display.setRefreshRateZoneId(d.getRefreshRateZoneId());
+ display.setRefreshRateThermalThrottlingMapId(
+ d.getRefreshRateThermalThrottlingMapId());
}
}
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 7b560ce..d57dc47 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -22,6 +22,7 @@
import android.graphics.Rect;
import android.hardware.display.DisplayViewport;
import android.os.IBinder;
+import android.util.Slog;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.Surface;
@@ -39,6 +40,7 @@
* </p>
*/
abstract class DisplayDevice {
+ private static final String TAG = "DisplayDevice";
private static final Display.Mode EMPTY_DISPLAY_MODE = new Display.Mode.Builder().build();
private final DisplayAdapter mDisplayAdapter;
@@ -269,10 +271,13 @@
/**
* Sets the display layer stack while in a transaction.
*/
- public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
+ public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack,
+ int layerStackTag) {
if (mCurrentLayerStack != layerStack) {
mCurrentLayerStack = layerStack;
t.setDisplayLayerStack(mDisplayToken, layerStack);
+ Slog.i(TAG, "[" + layerStackTag + "] Layerstack set to " + layerStack + " for "
+ + mUniqueId);
}
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 75f8acc..cdab77d 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -31,6 +31,7 @@
import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Spline;
import android.view.DisplayAddress;
import android.view.SurfaceControl;
@@ -54,6 +55,8 @@
import com.android.server.display.config.Point;
import com.android.server.display.config.RefreshRateConfigs;
import com.android.server.display.config.RefreshRateRange;
+import com.android.server.display.config.RefreshRateThrottlingMap;
+import com.android.server.display.config.RefreshRateThrottlingPoint;
import com.android.server.display.config.RefreshRateZone;
import com.android.server.display.config.SdrHdrRatioMap;
import com.android.server.display.config.SdrHdrRatioPoint;
@@ -88,6 +91,7 @@
* <pre>
* {@code
* <displayConfiguration>
+ * <name>Built-In Display</name>
* <densityMapping>
* <density>
* <height>480</height>
@@ -149,9 +153,26 @@
* <brightness>0.005</brightness>
* </brightnessThrottlingPoint>
* </concurrentDisplaysBrightnessThrottlingMap>
+ * <refreshRateThrottlingMap>
+ * <refreshRateThrottlingPoint>
+ * <thermalStatus>critical</thermalStatus>
+ * <refreshRateRange>
+ * <minimum>0</minimum>
+ * <maximum>60</maximum>
+ * </refreshRateRange>
+ * </refreshRateThrottlingPoint>
+ * </refreshRateThrottlingMap>
* </thermalThrottling>
*
* <refreshRate>
+ * <refreshRateZoneProfiles>
+ * <refreshRateZoneProfile id="concurrent">
+ * <refreshRateRange>
+ * <minimum>60</minimum>
+ * <maximum>60</maximum>
+ * </refreshRateRange>
+ * </refreshRateZoneProfile>
+ * </refreshRateZoneProfiles>
* <defaultRefreshRateInHbmHdr>75</defaultRefreshRateInHbmHdr>
* <defaultRefreshRateInHbmSunlight>75</defaultRefreshRateInHbmSunlight>
* <lowerBlockingZoneConfigs>
@@ -417,7 +438,7 @@
public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";
- static final String DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID = "default";
+ static final String DEFAULT_ID = "default";
private static final float BRIGHTNESS_DEFAULT = 0.5f;
private static final String ETC_DIR = "etc";
@@ -479,6 +500,10 @@
private final List<RefreshRateLimitation> mRefreshRateLimitations =
new ArrayList<>(2 /*initialCapacity*/);
+ // Name of the display, if configured.
+ @Nullable
+ private String mName;
+
// Nits and backlight values that are loaded from either the display device config file, or
// config.xml. These are the raw values and just used for the dumpsys
private float[] mRawNits;
@@ -662,7 +687,11 @@
private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
- private Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap = new HashMap();
+ private final Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap =
+ new HashMap<>();
+
+ private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
+ mRefreshRateThrottlingMap = new HashMap<>();
@Nullable
private HostUsiVersion mHostUsiVersion;
@@ -808,6 +837,15 @@
return config;
}
+ /** The name of the display.
+ *
+ * @return The name of the display.
+ */
+ @Nullable
+ public String getName() {
+ return mName;
+ }
+
/**
* Return the brightness mapping nits array.
*
@@ -1315,6 +1353,17 @@
}
/**
+ * @param id - throttling data id or null for default
+ * @return refresh rate throttling configuration
+ */
+ @Nullable
+ public SparseArray<SurfaceControl.RefreshRateRange> getRefreshRateThrottlingData(
+ @Nullable String id) {
+ String key = id == null ? DEFAULT_ID : id;
+ return mRefreshRateThrottlingMap.get(key);
+ }
+
+ /**
* @return Auto brightness darkening light debounce
*/
public long getAutoBrightnessDarkeningLightDebounce() {
@@ -1552,6 +1601,8 @@
+ ", mRefreshRateZoneProfiles= " + mRefreshRateZoneProfiles
+ ", mDefaultRefreshRateInHbmHdr= " + mDefaultRefreshRateInHbmHdr
+ ", mDefaultRefreshRateInHbmSunlight= " + mDefaultRefreshRateInHbmSunlight
+ + ", mRefreshRateThrottlingMap= " + mRefreshRateThrottlingMap
+ + "\n"
+ ", mLowDisplayBrightnessThresholds= "
+ Arrays.toString(mLowDisplayBrightnessThresholds)
+ ", mLowAmbientBrightnessThresholds= "
@@ -1609,11 +1660,12 @@
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
final DisplayConfiguration config = XmlParser.read(in);
if (config != null) {
+ loadName(config);
loadDensityMapping(config);
loadBrightnessDefaultFromDdcXml(config);
loadBrightnessConstraintsFromConfigXml();
loadBrightnessMap(config);
- loadBrightnessThrottlingMaps(config);
+ loadThermalThrottlingConfig(config);
loadHighBrightnessModeData(config);
loadQuirks(config);
loadBrightnessRamps(config);
@@ -1680,6 +1732,10 @@
}
}
+ private void loadName(DisplayConfiguration config) {
+ mName = config.getName();
+ }
+
private void loadDensityMapping(DisplayConfiguration config) {
if (config.getDensityMapping() == null) {
return;
@@ -1823,13 +1879,17 @@
return Spline.createSpline(nits, ratios);
}
- private void loadBrightnessThrottlingMaps(DisplayConfiguration config) {
+ private void loadThermalThrottlingConfig(DisplayConfiguration config) {
final ThermalThrottling throttlingConfig = config.getThermalThrottling();
if (throttlingConfig == null) {
Slog.i(TAG, "No thermal throttling config found");
return;
}
+ loadBrightnessThrottlingMaps(throttlingConfig);
+ loadRefreshRateThermalThrottlingMap(throttlingConfig);
+ }
+ private void loadBrightnessThrottlingMaps(ThermalThrottling throttlingConfig) {
final List<BrightnessThrottlingMap> maps = throttlingConfig.getBrightnessThrottlingMap();
if (maps == null || maps.isEmpty()) {
Slog.i(TAG, "No brightness throttling map found");
@@ -1855,7 +1915,7 @@
}
if (!badConfig) {
- String id = map.getId() == null ? DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+ String id = map.getId() == null ? DEFAULT_ID
: map.getId();
if (mBrightnessThrottlingDataMap.containsKey(id)) {
throw new RuntimeException("Brightness throttling data with ID " + id
@@ -1867,6 +1927,57 @@
}
}
+ private void loadRefreshRateThermalThrottlingMap(ThermalThrottling throttlingConfig) {
+ List<RefreshRateThrottlingMap> maps = throttlingConfig.getRefreshRateThrottlingMap();
+ if (maps == null || maps.isEmpty()) {
+ Slog.w(TAG, "RefreshRateThrottling: map not found");
+ return;
+ }
+
+ for (RefreshRateThrottlingMap map : maps) {
+ List<RefreshRateThrottlingPoint> points = map.getRefreshRateThrottlingPoint();
+ String id = map.getId() == null ? DEFAULT_ID : map.getId();
+
+ if (points == null || points.isEmpty()) {
+ // Expected at lease 1 throttling point for each map
+ Slog.w(TAG, "RefreshRateThrottling: points not found for mapId=" + id);
+ continue;
+ }
+ if (mRefreshRateThrottlingMap.containsKey(id)) {
+ Slog.wtf(TAG, "RefreshRateThrottling: map already exists, mapId=" + id);
+ continue;
+ }
+
+ SparseArray<SurfaceControl.RefreshRateRange> refreshRates = new SparseArray<>();
+ for (RefreshRateThrottlingPoint point : points) {
+ ThermalStatus status = point.getThermalStatus();
+ if (!thermalStatusIsValid(status)) {
+ Slog.wtf(TAG,
+ "RefreshRateThrottling: Invalid thermalStatus=" + status.getRawName()
+ + ",mapId=" + id);
+ continue;
+ }
+ int thermalStatusInt = convertThermalStatus(status);
+ if (refreshRates.contains(thermalStatusInt)) {
+ Slog.wtf(TAG, "RefreshRateThrottling: thermalStatus=" + status.getRawName()
+ + " is already in the map, mapId=" + id);
+ continue;
+ }
+
+ refreshRates.put(thermalStatusInt, new SurfaceControl.RefreshRateRange(
+ point.getRefreshRateRange().getMinimum().floatValue(),
+ point.getRefreshRateRange().getMaximum().floatValue()
+ ));
+ }
+ if (refreshRates.size() == 0) {
+ Slog.w(TAG, "RefreshRateThrottling: no valid throttling points fond for map, mapId="
+ + id);
+ continue;
+ }
+ mRefreshRateThrottlingMap.put(id, refreshRates);
+ }
+ }
+
private void loadRefreshRateSetting(DisplayConfiguration config) {
final RefreshRateConfigs refreshRateConfigs =
(config == null) ? null : config.getRefreshRate();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 214c591..21cc172 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2105,8 +2105,7 @@
}
}
- // TODO (b/264979880) - Add unit test for HDR output control methods.
- private void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
+ void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
if (!mInjector.getHdrOutputConversionSupport()) {
return;
}
@@ -2140,7 +2139,7 @@
}
}
- private HdrConversionMode getHdrConversionModeSettingInternal() {
+ HdrConversionMode getHdrConversionModeSettingInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
return HDR_CONVERSION_MODE_UNSUPPORTED;
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index da8e6a6..84fe8f2 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -885,7 +885,7 @@
final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
final String brightnessThrottlingDataId =
mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
- mHandler.post(() -> {
+ mHandler.postAtTime(() -> {
boolean changed = false;
if (mDisplayDevice != device) {
changed = true;
@@ -916,7 +916,7 @@
if (changed) {
updatePowerState();
}
- });
+ }, mClock.uptimeMillis());
}
/**
@@ -940,10 +940,6 @@
mAutomaticBrightnessController.stop();
}
- if (mScreenOffBrightnessSensorController != null) {
- mScreenOffBrightnessSensorController.stop();
- }
-
if (mBrightnessSetting != null) {
mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
}
@@ -1190,6 +1186,7 @@
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.stop();
+ mScreenOffBrightnessSensorController = null;
}
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
@@ -1311,6 +1308,10 @@
mPowerState.stop();
mPowerState = null;
}
+
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ }
}
private void updatePowerState() {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index a2a53e3..297a6f8 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -729,7 +729,7 @@
final String brightnessThrottlingDataId =
mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
- mHandler.post(() -> {
+ mHandler.postAtTime(() -> {
boolean changed = false;
if (mDisplayDevice != device) {
changed = true;
@@ -761,7 +761,7 @@
if (changed) {
updatePowerState();
}
- });
+ }, mClock.uptimeMillis());
}
/**
@@ -1028,6 +1028,10 @@
mBrightnessEventRingBuffer =
new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ mScreenOffBrightnessSensorController = null;
+ }
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
@@ -1133,6 +1137,10 @@
mPowerState.stop();
mPowerState = null;
}
+
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ }
}
private void updatePowerState() {
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 58c5034..8d0689f 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -42,6 +42,7 @@
import android.view.RoundedCorners;
import android.view.SurfaceControl;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -675,14 +676,13 @@
mInfo.flags |= DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
if (mIsFirstDisplay) {
- if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
+ if (res.getBoolean(R.bool.config_mainBuiltInDisplayIsRound)
|| (Build.IS_EMULATOR
&& SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
}
} else {
- if (!res.getBoolean(
- com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
+ if (!res.getBoolean(R.bool.config_localDisplaysMirrorContent)) {
mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
}
@@ -711,18 +711,23 @@
mInfo.displayShape = DisplayShape.fromResources(
res, mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height);
+ mInfo.name = getDisplayDeviceConfig().getName();
+
if (mStaticDisplayInfo.isInternal) {
mInfo.type = Display.TYPE_INTERNAL;
mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
- mInfo.name = res.getString(
- com.android.internal.R.string.display_manager_built_in_display_name);
+ if (mInfo.name == null) {
+ mInfo.name = res.getString(R.string.display_manager_built_in_display_name);
+ }
} else {
mInfo.type = Display.TYPE_EXTERNAL;
mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
- mInfo.name = getContext().getResources().getString(
- com.android.internal.R.string.display_manager_hdmi_display_name);
+ if (mInfo.name == null) {
+ mInfo.name = getContext().getResources().getString(
+ R.string.display_manager_hdmi_display_name);
+ }
}
mInfo.frameRateOverrides = mFrameRateOverrides;
@@ -1255,8 +1260,7 @@
return false;
}
final Resources res = getOverlayContext().getResources();
- int[] ports = res.getIntArray(
- com.android.internal.R.array.config_localPrivateDisplayPorts);
+ int[] ports = res.getIntArray(R.array.config_localPrivateDisplayPorts);
if (ports != null) {
int port = physicalAddress.getPort();
for (int p : ports) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 78c597e..dee4cde 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -189,7 +189,7 @@
mTempFrameRateOverride = new SparseArray<>();
mIsEnabled = true;
mIsInTransition = false;
- mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID;
+ mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_ID;
}
public void setDevicePositionLocked(int position) {
@@ -344,6 +344,21 @@
mInfo.set(null);
}
}
+ /**
+ * Updates refreshRateThermalThrottling
+ *
+ * @param refreshRanges new refreshRateThermalThrottling ranges limited by layout or default
+ */
+ public void updateRefreshRateThermalThrottling(
+ @Nullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges) {
+ if (refreshRanges == null) {
+ refreshRanges = new SparseArray<>();
+ }
+ if (!mBaseDisplayInfo.refreshRateThermalThrottling.contentEquals(refreshRanges)) {
+ mBaseDisplayInfo.refreshRateThermalThrottling = refreshRanges;
+ mInfo.set(null);
+ }
+ }
/**
* Updates the state of the logical display based on the available display devices.
@@ -572,7 +587,7 @@
DisplayDevice device,
boolean isBlanked) {
// Set the layer stack.
- device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+ device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack, mDisplayId);
// Also inform whether the device is the same one sent to inputflinger for its layerstack.
// Prevent displays that are disabled from receiving input.
// TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 2ac7d9d..e290b7a 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -1013,19 +1013,23 @@
if (newDisplay != oldDisplay) {
newDisplay.swapDisplaysLocked(oldDisplay);
}
+ DisplayDeviceConfig config = device.getDisplayDeviceConfig();
newDisplay.setDevicePositionLocked(displayLayout.getPosition());
newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId());
newDisplay.updateLayoutLimitedRefreshRateLocked(
- device.getDisplayDeviceConfig().getRefreshRange(
- displayLayout.getRefreshRateZoneId()
+ config.getRefreshRange(displayLayout.getRefreshRateZoneId())
+ );
+ newDisplay.updateRefreshRateThermalThrottling(
+ config.getRefreshRateThrottlingData(
+ displayLayout.getRefreshRateThermalThrottlingMapId()
)
);
setEnabledLocked(newDisplay, displayLayout.isEnabled());
newDisplay.setBrightnessThrottlingDataIdLocked(
displayLayout.getBrightnessThrottlingMapId() == null
- ? DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+ ? DisplayDeviceConfig.DEFAULT_ID
: displayLayout.getBrightnessThrottlingMapId());
newDisplay.setDisplayGroupNameLocked(displayLayout.getDisplayGroupName());
diff --git a/services/core/java/com/android/server/display/layout/Layout.java b/services/core/java/com/android/server/display/layout/Layout.java
index f1e885e..6a4d23b 100644
--- a/services/core/java/com/android/server/display/layout/Layout.java
+++ b/services/core/java/com/android/server/display/layout/Layout.java
@@ -257,6 +257,9 @@
@Nullable
private String mRefreshRateZoneId;
+ @Nullable
+ private String mRefreshRateThermalThrottlingMapId;
+
Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled,
@NonNull String displayGroupName, String brightnessThrottlingMapId, int position,
int leadDisplayId) {
@@ -286,6 +289,7 @@
+ ", brightnessThrottlingMapId: " + mBrightnessThrottlingMapId
+ ", mRefreshRateZoneId: " + mRefreshRateZoneId
+ ", mLeadDisplayId: " + mLeadDisplayId
+ + ", mRefreshRateThermalThrottlingMapId: " + mRefreshRateThermalThrottlingMapId
+ "}";
}
@@ -305,7 +309,9 @@
&& Objects.equals(mBrightnessThrottlingMapId,
otherDisplay.mBrightnessThrottlingMapId)
&& Objects.equals(otherDisplay.mRefreshRateZoneId, this.mRefreshRateZoneId)
- && this.mLeadDisplayId == otherDisplay.mLeadDisplayId;
+ && this.mLeadDisplayId == otherDisplay.mLeadDisplayId
+ && Objects.equals(mRefreshRateThermalThrottlingMapId,
+ otherDisplay.mRefreshRateThermalThrottlingMapId);
}
@Override
@@ -319,6 +325,7 @@
result = 31 * result + mBrightnessThrottlingMapId.hashCode();
result = 31 * result + Objects.hashCode(mRefreshRateZoneId);
result = 31 * result + mLeadDisplayId;
+ result = 31 * result + Objects.hashCode(mRefreshRateThermalThrottlingMapId);
return result;
}
@@ -388,5 +395,13 @@
public int getLeadDisplayId() {
return mLeadDisplayId;
}
+
+ public void setRefreshRateThermalThrottlingMapId(String refreshRateThermalThrottlingMapId) {
+ mRefreshRateThermalThrottlingMapId = refreshRateThermalThrottlingMapId;
+ }
+
+ public String getRefreshRateThermalThrottlingMapId() {
+ return mRefreshRateThermalThrottlingMapId;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 24d5ca4..db6944d0 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -224,6 +224,7 @@
}
mLoggingEnabled = loggingEnabled;
mBrightnessObserver.setLoggingEnabled(loggingEnabled);
+ mSkinThermalStatusObserver.setLoggingEnabled(loggingEnabled);
}
@NonNull
@@ -2669,7 +2670,7 @@
}
}
- private static final class SensorObserver implements ProximityActiveListener,
+ protected static final class SensorObserver implements ProximityActiveListener,
DisplayManager.DisplayListener {
private final String mProximitySensorName = null;
private final String mProximitySensorType = Sensor.STRING_TYPE_PROXIMITY;
@@ -2952,52 +2953,6 @@
}
}
- private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
- private final BallotBox mBallotBox;
- private final Injector mInjector;
-
- private @Temperature.ThrottlingStatus int mStatus = -1;
-
- SkinThermalStatusObserver(Injector injector, BallotBox ballotBox) {
- mInjector = injector;
- mBallotBox = ballotBox;
- }
-
- @Override
- public void notifyThrottling(Temperature temp) {
- mStatus = temp.getStatus();
- if (mLoggingEnabled) {
- Slog.d(TAG, "New thermal throttling status "
- + ", current thermal status = " + mStatus);
- }
- final Vote vote;
- if (mStatus >= Temperature.THROTTLING_CRITICAL) {
- vote = Vote.forRenderFrameRates(0f, 60f);
- } else {
- vote = null;
- }
- mBallotBox.vote(GLOBAL_ID, Vote.PRIORITY_SKIN_TEMPERATURE, vote);
- }
-
- public void observe() {
- IThermalService thermalService = mInjector.getThermalService();
- if (thermalService == null) {
- Slog.w(TAG, "Could not observe thermal status. Service not available");
- return;
- }
- try {
- thermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to register thermal status listener", e);
- }
- }
-
- void dumpLocked(PrintWriter writer) {
- writer.println(" SkinThermalStatusObserver:");
- writer.println(" mStatus: " + mStatus);
- }
- }
-
private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
public void startListening() {
mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
@@ -3184,11 +3139,15 @@
void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
Handler handler, long flags);
+ Display[] getDisplays();
+
+ boolean getDisplayInfo(int displayId, DisplayInfo displayInfo);
+
BrightnessInfo getBrightnessInfo(int displayId);
boolean isDozeState(Display d);
- IThermalService getThermalService();
+ boolean registerThermalServiceListener(IThermalEventListener listener);
boolean supportsFrameRateOverride();
}
@@ -3222,6 +3181,20 @@
}
@Override
+ public Display[] getDisplays() {
+ return getDisplayManager().getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+ }
+
+ @Override
+ public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+ Display display = getDisplayManager().getDisplay(displayId);
+ if (display != null) {
+ return display.getDisplayInfo(displayInfo);
+ }
+ return false;
+ }
+
+ @Override
public BrightnessInfo getBrightnessInfo(int displayId) {
final Display display = getDisplayManager().getDisplay(displayId);
if (display != null) {
@@ -3239,9 +3212,20 @@
}
@Override
- public IThermalService getThermalService() {
- return IThermalService.Stub.asInterface(
- ServiceManager.getService(Context.THERMAL_SERVICE));
+ public boolean registerThermalServiceListener(IThermalEventListener listener) {
+ IThermalService thermalService = getThermalService();
+ if (thermalService == null) {
+ Slog.w(TAG, "Could not observe thermal status. Service not available");
+ return false;
+ }
+ try {
+ thermalService.registerThermalEventListenerWithType(listener,
+ Temperature.TYPE_SKIN);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register thermal status listener", e);
+ return false;
+ }
+ return true;
}
@Override
@@ -3255,6 +3239,11 @@
}
return mDisplayManager;
}
+
+ private IThermalService getThermalService() {
+ return IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+ }
}
interface BallotBox {
diff --git a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
new file mode 100644
index 0000000..1bb34ab
--- /dev/null
+++ b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2023 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.display.mode;
+
+import android.annotation.Nullable;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
+import java.io.PrintWriter;
+
+final class SkinThermalStatusObserver extends IThermalEventListener.Stub implements
+ DisplayManager.DisplayListener {
+ private static final String TAG = "SkinThermalStatusObserver";
+
+ private final DisplayModeDirector.BallotBox mBallotBox;
+ private final DisplayModeDirector.Injector mInjector;
+
+ private boolean mLoggingEnabled;
+
+ private final Handler mHandler;
+ private final Object mThermalObserverLock = new Object();
+ @GuardedBy("mThermalObserverLock")
+ @Temperature.ThrottlingStatus
+ private int mStatus = -1;
+ @GuardedBy("mThermalObserverLock")
+ private final SparseArray<SparseArray<SurfaceControl.RefreshRateRange>>
+ mThermalThrottlingByDisplay = new SparseArray<>();
+
+ SkinThermalStatusObserver(DisplayModeDirector.Injector injector,
+ DisplayModeDirector.BallotBox ballotBox) {
+ this(injector, ballotBox, BackgroundThread.getHandler());
+ }
+
+ @VisibleForTesting
+ SkinThermalStatusObserver(DisplayModeDirector.Injector injector,
+ DisplayModeDirector.BallotBox ballotBox, Handler handler) {
+ mInjector = injector;
+ mBallotBox = ballotBox;
+ mHandler = handler;
+ }
+
+ void observe() {
+ // if failed to register thermal service listener, don't register display listener
+ if (!mInjector.registerThermalServiceListener(this)) {
+ return;
+ }
+
+ mInjector.registerDisplayListener(this, mHandler,
+ DisplayManager.EVENT_FLAG_DISPLAY_ADDED | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+
+ populateInitialDisplayInfo();
+ }
+
+ void setLoggingEnabled(boolean enabled) {
+ mLoggingEnabled = enabled;
+ }
+
+ @Override
+ public void notifyThrottling(Temperature temp) {
+ @Temperature.ThrottlingStatus int currentStatus = temp.getStatus();
+ synchronized (mThermalObserverLock) {
+ mStatus = currentStatus;
+ mHandler.post(this::updateVotes);
+ }
+
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "New thermal throttling status " + ", current thermal status = "
+ + currentStatus);
+ }
+ }
+
+ //region DisplayManager.DisplayListener
+ @Override
+ public void onDisplayAdded(int displayId) {
+ updateRefreshRateThermalThrottling(displayId);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display added:" + displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ synchronized (mThermalObserverLock) {
+ mThermalThrottlingByDisplay.remove(displayId);
+ mHandler.post(() -> mBallotBox.vote(displayId,
+ DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, null));
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display removed and voted: displayId=" + displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ updateRefreshRateThermalThrottling(displayId);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display changed:" + displayId);
+ }
+ }
+ //endregion
+
+ private void populateInitialDisplayInfo() {
+ DisplayInfo info = new DisplayInfo();
+ Display[] displays = mInjector.getDisplays();
+ int size = displays.length;
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap = new SparseArray<>(
+ size);
+ for (Display d : displays) {
+ final int displayId = d.getDisplayId();
+ d.getDisplayInfo(info);
+ localMap.put(displayId, info.refreshRateThermalThrottling);
+ }
+ synchronized (mThermalObserverLock) {
+ for (int i = 0; i < size; i++) {
+ mThermalThrottlingByDisplay.put(localMap.keyAt(i), localMap.valueAt(i));
+ }
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display initial info:" + localMap);
+ }
+ }
+
+ private void updateRefreshRateThermalThrottling(int displayId) {
+ DisplayInfo displayInfo = new DisplayInfo();
+ mInjector.getDisplayInfo(displayId, displayInfo);
+ SparseArray<SurfaceControl.RefreshRateRange> throttlingMap =
+ displayInfo.refreshRateThermalThrottling;
+
+ synchronized (mThermalObserverLock) {
+ mThermalThrottlingByDisplay.put(displayId, throttlingMap);
+ mHandler.post(() -> updateVoteForDisplay(displayId));
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG,
+ "Thermal throttling updated: display=" + displayId + ", map=" + throttlingMap);
+ }
+ }
+
+ //region in mHandler thread
+ private void updateVotes() {
+ @Temperature.ThrottlingStatus int localStatus;
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap;
+
+ synchronized (mThermalObserverLock) {
+ localStatus = mStatus;
+ localMap = mThermalThrottlingByDisplay.clone();
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Updating votes for status=" + localStatus + ", map=" + localMap);
+ }
+ int size = localMap.size();
+ for (int i = 0; i < size; i++) {
+ reportThrottlingIfNeeded(localMap.keyAt(i), localStatus, localMap.valueAt(i));
+ }
+ }
+
+ private void updateVoteForDisplay(int displayId) {
+ @Temperature.ThrottlingStatus int localStatus;
+ SparseArray<SurfaceControl.RefreshRateRange> localMap;
+
+ synchronized (mThermalObserverLock) {
+ localStatus = mStatus;
+ localMap = mThermalThrottlingByDisplay.get(displayId);
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Updating votes for status=" + localStatus + ", display =" + displayId
+ + ", map=" + localMap);
+ }
+ reportThrottlingIfNeeded(displayId, localStatus, localMap);
+ }
+
+ private void reportThrottlingIfNeeded(int displayId,
+ @Temperature.ThrottlingStatus int currentStatus,
+ SparseArray<SurfaceControl.RefreshRateRange> throttlingMap) {
+ if (currentStatus == -1) { // no throttling status reported from thermal sensor yet
+ return;
+ }
+
+ if (throttlingMap.size() == 0) { // map is not configured, using default behaviour
+ fallbackReportThrottlingIfNeeded(displayId, currentStatus);
+ return;
+ }
+
+ SurfaceControl.RefreshRateRange foundRange = findBestMatchingRefreshRateRange(currentStatus,
+ throttlingMap);
+ // if status <= currentStatus not found in the map reset vote
+ DisplayModeDirector.Vote vote = null;
+ if (foundRange != null) { // otherwise vote with found range
+ vote = DisplayModeDirector.Vote.forRenderFrameRates(foundRange.min, foundRange.max);
+ }
+ mBallotBox.vote(displayId, DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, vote);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Voted: vote=" + vote + ", display =" + displayId);
+ }
+ }
+
+ @Nullable
+ private SurfaceControl.RefreshRateRange findBestMatchingRefreshRateRange(
+ @Temperature.ThrottlingStatus int currentStatus,
+ SparseArray<SurfaceControl.RefreshRateRange> throttlingMap) {
+ SurfaceControl.RefreshRateRange foundRange = null;
+ for (int status = currentStatus; status >= 0; status--) {
+ foundRange = throttlingMap.get(status);
+ if (foundRange != null) {
+ break;
+ }
+ }
+ return foundRange;
+ }
+
+ private void fallbackReportThrottlingIfNeeded(int displayId,
+ @Temperature.ThrottlingStatus int currentStatus) {
+ DisplayModeDirector.Vote vote = null;
+ if (currentStatus >= Temperature.THROTTLING_CRITICAL) {
+ vote = DisplayModeDirector.Vote.forRenderFrameRates(0f, 60f);
+ }
+ mBallotBox.vote(displayId, DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, vote);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Voted(fallback): vote=" + vote + ", display =" + displayId);
+ }
+ }
+ //endregion
+
+ void dumpLocked(PrintWriter writer) {
+ @Temperature.ThrottlingStatus int localStatus;
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap;
+
+ synchronized (mThermalObserverLock) {
+ localStatus = mStatus;
+ localMap = mThermalThrottlingByDisplay.clone();
+ }
+
+ writer.println(" SkinThermalStatusObserver:");
+ writer.println(" mStatus: " + localStatus);
+ writer.println(" mThermalThrottlingByDisplay: " + localMap);
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3563938..c0deb3f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -700,6 +700,7 @@
}
if (mCecController == null) {
Slog.i(TAG, "Device does not support HDMI-CEC.");
+ return;
}
if (mMhlController == null) {
mMhlController = HdmiMhlControllerStub.create(this);
@@ -713,9 +714,6 @@
if (mEarcController == null) {
Slog.i(TAG, "Device does not support eARC.");
}
- if (mCecController == null && mEarcController == null) {
- return;
- }
mHdmiCecNetwork = new HdmiCecNetwork(this, mCecController, mMhlController);
if (isCecControlEnabled()) {
initializeCec(INITIATED_BY_BOOT_UP);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index d397a0c..91f91f8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3325,6 +3325,7 @@
if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) {
ImeTracker.forLogging().onFailed(
statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return false;
}
final long ident = Binder.clearCallingIdentity();
@@ -6458,19 +6459,21 @@
0 /* flags */, null /* resultReceiver */,
SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
mBindingController.unbindCurrentMethod();
- // Reset the current IME
- resetSelectedInputMethodAndSubtypeLocked(null);
- // Also reset the settings of the current IME
- mSettings.putSelectedInputMethod(null);
- // Disable all enabled IMEs.
- for (InputMethodInfo inputMethodInfo :
- mSettings.getEnabledInputMethodListLocked()) {
- setInputMethodEnabledLocked(inputMethodInfo.getId(), false);
+
+ // Enable default IMEs, disable others
+ var toDisable = mSettings.getEnabledInputMethodListLocked();
+ var defaultEnabled = InputMethodInfoUtils.getDefaultEnabledImes(
+ mContext, mMethodList);
+ toDisable.removeAll(defaultEnabled);
+ for (InputMethodInfo info : toDisable) {
+ setInputMethodEnabledLocked(info.getId(), false);
}
- // Re-enable with default enabled IMEs.
- for (InputMethodInfo imi : InputMethodInfoUtils.getDefaultEnabledImes(
- mContext, mMethodList)) {
- setInputMethodEnabledLocked(imi.getId(), true);
+ for (InputMethodInfo info : defaultEnabled) {
+ setInputMethodEnabledLocked(info.getId(), true);
+ }
+ // Choose new default IME, reset to none if no IME available.
+ if (!chooseNewDefaultIMELocked()) {
+ resetSelectedInputMethodAndSubtypeLocked(null);
}
updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index ca184ee..1e32ad6 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.contexthub.HostEndpointInfo;
+import android.hardware.contexthub.NanSessionRequest;
import android.hardware.contexthub.V1_0.ContextHub;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.TransactionResult;
@@ -456,8 +457,8 @@
});
}
- public void handleNanSessionRequest(boolean enable) {
- // TODO(229888878): Implement
+ public void handleNanSessionRequest(NanSessionRequest request) {
+ // TODO(271471342): Implement
}
@Override
diff --git a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
index f5114b7..01c108b 100644
--- a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
+++ b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
@@ -37,7 +37,7 @@
* a platform bug. This switch will be removed in a future release. If there are problems with
* the new impl we'd like to hear about them.
*/
- static final boolean USE_TIME_DETECTOR_IMPL = false;
+ static final boolean USE_TIME_DETECTOR_IMPL = true;
/**
* The callback interface used by {@link NetworkTimeHelper} to report the time to {@link
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 925ab65..7aaf915 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -64,6 +64,7 @@
import android.location.LocationManagerInternal.ProviderEnabledListener;
import android.location.LocationRequest;
import android.location.LocationResult;
+import android.location.altitude.AltitudeConverter;
import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.location.provider.ProviderRequest;
@@ -81,6 +82,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.DeviceConfig;
import android.stats.location.LocationStatsEnums;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -94,6 +96,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
+import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.location.LocationPermissions;
import com.android.server.location.LocationPermissions.PermissionLevel;
@@ -122,6 +125,7 @@
import com.android.server.location.settings.LocationUserSettings;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -1441,6 +1445,10 @@
@GuardedBy("mMultiplexerLock")
@Nullable private StateChangedListener mStateChangedListener;
+ /** Enables missing MSL altitudes to be added on behalf of the provider. */
+ private final AltitudeConverter mAltitudeConverter = new AltitudeConverter();
+ private volatile boolean mIsAltitudeConverterIdle = true;
+
public LocationProviderManager(Context context, Injector injector,
String name, @Nullable PassiveLocationProviderManager passiveManager) {
this(context, injector, name, passiveManager, Collections.emptyList());
@@ -2512,33 +2520,18 @@
@GuardedBy("mMultiplexerLock")
@Override
public void onReportLocation(LocationResult locationResult) {
- LocationResult filtered;
+ LocationResult processed;
if (mPassiveManager != null) {
- filtered = locationResult.filter(location -> {
- if (!location.isMock()) {
- if (location.getLatitude() == 0 && location.getLongitude() == 0) {
- Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
- return false;
- }
- }
-
- if (!location.isComplete()) {
- Log.e(TAG, "blocking incomplete location from " + mName + " provider");
- return false;
- }
-
- return true;
- });
-
- if (filtered == null) {
+ processed = processReportedLocation(locationResult);
+ if (processed == null) {
return;
}
// don't log location received for passive provider because it's spammy
- EVENT_LOG.logProviderReceivedLocations(mName, filtered.size());
+ EVENT_LOG.logProviderReceivedLocations(mName, processed.size());
} else {
- // passive provider should get already filtered results as input
- filtered = locationResult;
+ // passive provider should get already processed results as input
+ processed = locationResult;
}
// check for non-monotonic locations if we're not the passive manager. the passive manager
@@ -2554,20 +2547,78 @@
}
// update last location
- setLastLocation(filtered.getLastLocation(), UserHandle.USER_ALL);
+ setLastLocation(processed.getLastLocation(), UserHandle.USER_ALL);
// attempt listener delivery
deliverToListeners(registration -> {
- return registration.acceptLocationChange(filtered);
+ return registration.acceptLocationChange(processed);
});
// notify passive provider
if (mPassiveManager != null) {
- mPassiveManager.updateLocation(filtered);
+ mPassiveManager.updateLocation(processed);
}
}
@GuardedBy("mMultiplexerLock")
+ @Nullable
+ private LocationResult processReportedLocation(LocationResult locationResult) {
+ LocationResult processed = locationResult.filter(location -> {
+ if (!location.isMock()) {
+ if (location.getLatitude() == 0 && location.getLongitude() == 0) {
+ Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
+ return false;
+ }
+ }
+
+ if (!location.isComplete()) {
+ Log.e(TAG, "blocking incomplete location from " + mName + " provider");
+ return false;
+ }
+
+ return true;
+ });
+ if (processed == null) {
+ return null;
+ }
+
+ // Attempt to add a missing MSL altitude on behalf of the provider.
+ if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_LOCATION,
+ "enable_location_provider_manager_msl", false)) {
+ return processed.map(location -> {
+ if (!location.hasMslAltitude() && location.hasAltitude()) {
+ try {
+ Location locationCopy = new Location(location);
+ if (mAltitudeConverter.addMslAltitudeToLocation(locationCopy)) {
+ return locationCopy;
+ }
+ // Only queue up one IO thread runnable.
+ if (mIsAltitudeConverterIdle) {
+ mIsAltitudeConverterIdle = false;
+ IoThread.getExecutor().execute(() -> {
+ try {
+ // Results added to the location copy are essentially discarded.
+ // We only rely on the side effect of loading altitude assets
+ // into the converter's memory cache.
+ mAltitudeConverter.addMslAltitudeToLocation(mContext,
+ locationCopy);
+ } catch (IOException e) {
+ Log.e(TAG, "not loading MSL altitude assets: " + e);
+ }
+ mIsAltitudeConverterIdle = true;
+ });
+ }
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "not adding MSL altitude to location: " + e);
+ }
+ }
+ return location;
+ });
+ }
+ return processed;
+ }
+
+ @GuardedBy("mMultiplexerLock")
private void onUserStarted(int userId) {
if (userId == UserHandle.USER_NULL) {
return;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 38fd69f..0476f2c 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -81,7 +81,6 @@
import android.hardware.fingerprint.FingerprintManager;
import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -116,7 +115,6 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
-import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -200,7 +198,6 @@
private static final String TAG = "LockSettingsService";
private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
private static final String BIOMETRIC_PERMISSION = MANAGE_BIOMETRIC;
- private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.DEBUG);
private static final int PROFILE_KEY_IV_SIZE = 12;
private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
@@ -686,8 +683,8 @@
PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
- Slog.d(TAG, TextUtils.formatSimple("showing encryption notification, user: %d; reason: %s",
- user.getIdentifier(), reason));
+ Slogf.d(TAG, "Showing encryption notification for user %d; reason: %s",
+ user.getIdentifier(), reason);
showEncryptionNotification(user, title, message, detail, intent);
}
@@ -731,7 +728,7 @@
}
private void hideEncryptionNotification(UserHandle userHandle) {
- Slog.d(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
+ Slogf.d(TAG, "Hiding encryption notification for user %d", userHandle.getIdentifier());
mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
userHandle);
}
@@ -1029,7 +1026,7 @@
private void enforceFrpResolved() {
final int mainUserId = mInjector.getUserManagerInternal().getMainUserId();
if (mainUserId < 0) {
- Slog.i(TAG, "No Main user on device; skip enforceFrpResolved");
+ Slog.d(TAG, "No Main user on device; skipping enforceFrpResolved");
return;
}
final ContentResolver cr = mContext.getContentResolver();
@@ -1995,7 +1992,7 @@
@Override
public void resetKeyStore(int userId) {
checkWritePermission();
- if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
+ Slogf.d(TAG, "Resetting keystore for user %d", userId);
List<Integer> profileUserIds = new ArrayList<>();
List<LockscreenCredential> profileUserDecryptedPasswords = new ArrayList<>();
final List<UserInfo> profiles = mUserManager.getProfiles(userId);
@@ -2032,7 +2029,6 @@
int piUserId = profileUserIds.get(i);
LockscreenCredential piUserDecryptedPassword = profileUserDecryptedPasswords.get(i);
if (piUserId != -1 && piUserDecryptedPassword != null) {
- if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
tieProfileLockToParent(piUserId, userId, piUserDecryptedPassword);
}
if (piUserDecryptedPassword != null) {
diff --git a/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
index 58fdb57..eb997ba 100644
--- a/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -18,7 +18,6 @@
import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_AUDIO;
import static android.bluetooth.BluetoothAdapter.STATE_CONNECTED;
-import static android.bluetooth.BluetoothAdapter.STATE_DISCONNECTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -37,18 +36,18 @@
import android.media.MediaRoute2Info;
import android.os.UserHandle;
import android.text.TextUtils;
-import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -61,58 +60,70 @@
* <p>Selected route override should be used by {@link AudioManager} which is aware of Audio
* Policies.
*/
-class AudioPoliciesBluetoothRouteController implements BluetoothRouteController {
+/* package */ class AudioPoliciesBluetoothRouteController
+ implements BluetoothRouteController {
private static final String TAG = "APBtRouteController";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
private static final String LE_AUDIO_ROUTE_ID_PREFIX = "LE_AUDIO_";
- // Maps hardware address to BluetoothRouteInfo
- private final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
- private final List<BluetoothRouteInfo> mActiveRoutes = new ArrayList<>();
-
- // Route type -> volume map
- private final SparseIntArray mVolumeMap = new SparseIntArray();
-
- private final Context mContext;
- private final BluetoothAdapter mBluetoothAdapter;
- private final BluetoothRoutesUpdatedListener mListener;
- private final AudioManager mAudioManager;
- private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener();
-
+ @NonNull
private final AdapterStateChangedReceiver mAdapterStateChangedReceiver =
new AdapterStateChangedReceiver();
+
+ @NonNull
private final DeviceStateChangedReceiver mDeviceStateChangedReceiver =
new DeviceStateChangedReceiver();
- private BluetoothA2dp mA2dpProfile;
- private BluetoothHearingAid mHearingAidProfile;
- private BluetoothLeAudio mLeAudioProfile;
+ @NonNull
+ private final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
- AudioPoliciesBluetoothRouteController(Context context, BluetoothAdapter btAdapter,
- BluetoothRoutesUpdatedListener listener) {
- mContext = context;
- mBluetoothAdapter = btAdapter;
- mListener = listener;
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- buildBluetoothRoutes();
+ @NonNull
+ private final SparseIntArray mVolumeMap = new SparseIntArray();
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final BluetoothAdapter mBluetoothAdapter;
+ @NonNull
+ private final BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+ @NonNull
+ private final BluetoothProfileMonitor mBluetoothProfileMonitor;
+ @NonNull
+ private final AudioManager mAudioManager;
+
+ @Nullable
+ private BluetoothRouteInfo mSelectedBluetoothRoute;
+
+ AudioPoliciesBluetoothRouteController(@NonNull Context context,
+ @NonNull BluetoothAdapter bluetoothAdapter,
+ @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+ this(context, bluetoothAdapter,
+ new BluetoothProfileMonitor(context, bluetoothAdapter), listener);
}
- /**
- * Registers listener to bluetooth status changes as the provided user.
- *
- * The registered receiver listens to {@link BluetoothA2dp#ACTION_ACTIVE_DEVICE_CHANGED} and
- * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED } events for {@link BluetoothProfile#A2DP},
- * {@link BluetoothProfile#HEARING_AID}, and {@link BluetoothProfile#LE_AUDIO} bluetooth profiles.
- *
- * @param user {@code UserHandle} as which receiver is registered
- */
+ @VisibleForTesting
+ AudioPoliciesBluetoothRouteController(@NonNull Context context,
+ @NonNull BluetoothAdapter bluetoothAdapter,
+ @NonNull BluetoothProfileMonitor bluetoothProfileMonitor,
+ @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(bluetoothAdapter);
+ Objects.requireNonNull(bluetoothProfileMonitor);
+ Objects.requireNonNull(listener);
+
+ mContext = context;
+ mBluetoothAdapter = bluetoothAdapter;
+ mBluetoothProfileMonitor = bluetoothProfileMonitor;
+ mAudioManager = mContext.getSystemService(AudioManager.class);
+ mListener = listener;
+
+ updateBluetoothRoutes();
+ }
+
@Override
public void start(UserHandle user) {
- mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
- mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
- mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
+ mBluetoothProfileMonitor.start();
IntentFilter adapterStateChangedIntentFilter = new IntentFilter();
@@ -143,22 +154,59 @@
}
@Override
- public boolean selectRoute(String deviceAddress) {
- // Temporary no-op.
- return false;
+ public boolean selectRoute(@Nullable String deviceAddress) {
+ synchronized (this) {
+ // Fetch all available devices in order to avoid race conditions with Bluetooth stack.
+ updateBluetoothRoutes();
+
+ if (deviceAddress == null) {
+ mSelectedBluetoothRoute = null;
+ return true;
+ }
+
+ BluetoothRouteInfo bluetoothRouteInfo = mBluetoothRoutes.get(deviceAddress);
+
+ if (bluetoothRouteInfo == null) {
+ Slog.w(TAG, "Cannot find bluetooth route for " + deviceAddress);
+ return false;
+ }
+
+ mSelectedBluetoothRoute = bluetoothRouteInfo;
+ setRouteConnectionState(mSelectedBluetoothRoute, STATE_CONNECTED);
+
+ updateConnectivityStateForDevicesInTheSameGroup();
+
+ return true;
+ }
}
/**
- * Transfers to a given bluetooth route.
- * The dedicated BT device with the route would be activated.
+ * Updates connectivity state for devices in the same devices group.
*
- * @param routeId the id of the Bluetooth device. {@code null} denotes to clear the use of
- * BT routes.
+ * <p>{@link BluetoothProfile#LE_AUDIO} and {@link BluetoothProfile#HEARING_AID} support
+ * grouping devices. Devices that belong to the same group should have the same routeId but
+ * different physical address.
+ *
+ * <p>In case one of the devices from the group is selected then other devices should also
+ * reflect this by changing their connectivity status to
+ * {@link MediaRoute2Info#CONNECTION_STATE_CONNECTED}.
*/
+ private void updateConnectivityStateForDevicesInTheSameGroup() {
+ synchronized (this) {
+ for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+ if (TextUtils.equals(btRoute.mRoute.getId(), mSelectedBluetoothRoute.mRoute.getId())
+ && !TextUtils.equals(btRoute.mBtDevice.getAddress(),
+ mSelectedBluetoothRoute.mBtDevice.getAddress())) {
+ setRouteConnectionState(btRoute, STATE_CONNECTED);
+ }
+ }
+ }
+ }
+
@Override
public void transferTo(@Nullable String routeId) {
if (routeId == null) {
- clearActiveDevices();
+ mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_AUDIO);
return;
}
@@ -169,38 +217,38 @@
return;
}
- if (mBluetoothAdapter != null) {
- mBluetoothAdapter.setActiveDevice(btRouteInfo.mBtDevice, ACTIVE_DEVICE_AUDIO);
- }
+ mBluetoothAdapter.setActiveDevice(btRouteInfo.mBtDevice, ACTIVE_DEVICE_AUDIO);
}
- private BluetoothRouteInfo findBluetoothRouteWithRouteId(String routeId) {
+ @Nullable
+ private BluetoothRouteInfo findBluetoothRouteWithRouteId(@Nullable String routeId) {
if (routeId == null) {
return null;
}
- for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
- if (TextUtils.equals(btRouteInfo.mRoute.getId(), routeId)) {
- return btRouteInfo;
+ synchronized (this) {
+ for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
+ if (TextUtils.equals(btRouteInfo.mRoute.getId(), routeId)) {
+ return btRouteInfo;
+ }
}
}
return null;
}
- /**
- * Clears the active device for all known profiles.
- */
- private void clearActiveDevices() {
- if (mBluetoothAdapter != null) {
- mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_AUDIO);
- }
- }
-
- private void buildBluetoothRoutes() {
- mBluetoothRoutes.clear();
+ private void updateBluetoothRoutes() {
Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
- if (bondedDevices != null) {
+
+ if (bondedDevices == null) {
+ return;
+ }
+
+ synchronized (this) {
+ mBluetoothRoutes.clear();
+
+ // We need to query all available to BT stack devices in order to avoid inconsistency
+ // between external services, like, AndroidManager, and BT stack.
for (BluetoothDevice device : bondedDevices) {
- if (device.isConnected()) {
+ if (isDeviceConnected(device)) {
BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
if (newBtRoute.mConnectedProfiles.size() > 0) {
mBluetoothRoutes.put(device.getAddress(), newBtRoute);
@@ -210,20 +258,31 @@
}
}
+ @VisibleForTesting
+ /* package */ boolean isDeviceConnected(@NonNull BluetoothDevice device) {
+ return device.isConnected();
+ }
+
@Nullable
@Override
public MediaRoute2Info getSelectedRoute() {
- // For now, active routes can be multiple only when a pair of hearing aid devices is active.
- // Let the first active device represent them.
- return (mActiveRoutes.isEmpty() ? null : mActiveRoutes.get(0).mRoute);
+ synchronized (this) {
+ if (mSelectedBluetoothRoute == null) {
+ return null;
+ }
+
+ return mSelectedBluetoothRoute.mRoute;
+ }
}
@NonNull
@Override
public List<MediaRoute2Info> getTransferableRoutes() {
List<MediaRoute2Info> routes = getAllBluetoothRoutes();
- for (BluetoothRouteInfo btRoute : mActiveRoutes) {
- routes.remove(btRoute.mRoute);
+ synchronized (this) {
+ if (mSelectedBluetoothRoute != null) {
+ routes.remove(mSelectedBluetoothRoute.mRoute);
+ }
}
return routes;
}
@@ -240,22 +299,19 @@
routeIds.add(selectedRoute.getId());
}
- for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
- // A pair of hearing aid devices or having the same hardware address
- if (routeIds.contains(btRoute.mRoute.getId())) {
- continue;
+ synchronized (this) {
+ for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+ // A pair of hearing aid devices or having the same hardware address
+ if (routeIds.contains(btRoute.mRoute.getId())) {
+ continue;
+ }
+ routes.add(btRoute.mRoute);
+ routeIds.add(btRoute.mRoute.getId());
}
- routes.add(btRoute.mRoute);
- routeIds.add(btRoute.mRoute.getId());
}
return routes;
}
- /**
- * Updates the volume for {@link AudioManager#getDevicesForStream(int) devices}.
- *
- * @return true if devices can be handled by the provider.
- */
@Override
public boolean updateVolumeForDevices(int devices, int volume) {
int routeType;
@@ -270,32 +326,31 @@
} else {
return false;
}
- mVolumeMap.put(routeType, volume);
- boolean shouldNotify = false;
- for (BluetoothRouteInfo btRoute : mActiveRoutes) {
- if (btRoute.mRoute.getType() != routeType) {
- continue;
+ synchronized (this) {
+ mVolumeMap.put(routeType, volume);
+ if (mSelectedBluetoothRoute == null
+ || mSelectedBluetoothRoute.mRoute.getType() != routeType) {
+ return false;
}
- btRoute.mRoute = new MediaRoute2Info.Builder(btRoute.mRoute)
- .setVolume(volume)
- .build();
- shouldNotify = true;
+
+ mSelectedBluetoothRoute.mRoute =
+ new MediaRoute2Info.Builder(mSelectedBluetoothRoute.mRoute)
+ .setVolume(volume)
+ .build();
}
- if (shouldNotify) {
- notifyBluetoothRoutesUpdated();
- }
+
+ notifyBluetoothRoutesUpdated();
return true;
}
private void notifyBluetoothRoutesUpdated() {
- if (mListener != null) {
- mListener.onBluetoothRoutesUpdated(getAllBluetoothRoutes());
- }
+ mListener.onBluetoothRoutesUpdated(getAllBluetoothRoutes());
}
private BluetoothRouteInfo createBluetoothRoute(BluetoothDevice device) {
- BluetoothRouteInfo newBtRoute = new BluetoothRouteInfo();
+ BluetoothRouteInfo
+ newBtRoute = new BluetoothRouteInfo();
newBtRoute.mBtDevice = device;
String routeId = device.getAddress();
@@ -305,20 +360,20 @@
}
int type = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
newBtRoute.mConnectedProfiles = new SparseBooleanArray();
- if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) {
+ if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.A2DP, device)) {
newBtRoute.mConnectedProfiles.put(BluetoothProfile.A2DP, true);
}
- if (mHearingAidProfile != null
- && mHearingAidProfile.getConnectedDevices().contains(device)) {
+ if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.HEARING_AID, device)) {
newBtRoute.mConnectedProfiles.put(BluetoothProfile.HEARING_AID, true);
// Intentionally assign the same ID for a pair of devices to publish only one of them.
- routeId = HEARING_AID_ROUTE_ID_PREFIX + mHearingAidProfile.getHiSyncId(device);
+ routeId = HEARING_AID_ROUTE_ID_PREFIX
+ + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.HEARING_AID, device);
type = MediaRoute2Info.TYPE_HEARING_AID;
}
- if (mLeAudioProfile != null
- && mLeAudioProfile.getConnectedDevices().contains(device)) {
+ if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.LE_AUDIO, device)) {
newBtRoute.mConnectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
- routeId = LE_AUDIO_ROUTE_ID_PREFIX + mLeAudioProfile.getGroupId(device);
+ routeId = LE_AUDIO_ROUTE_ID_PREFIX
+ + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.LE_AUDIO, device);
type = MediaRoute2Info.TYPE_BLE_HEADSET;
}
@@ -351,72 +406,19 @@
.setConnectionState(state);
builder.setType(btRoute.getRouteType());
+
+
if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
- builder.setVolume(mVolumeMap.get(btRoute.getRouteType(), 0));
+ int currentVolume;
+ synchronized (this) {
+ currentVolume = mVolumeMap.get(btRoute.getRouteType(), 0);
+ }
+ builder.setVolume(currentVolume);
}
+
btRoute.mRoute = builder.build();
}
- private void addActiveRoute(BluetoothRouteInfo btRoute) {
- if (btRoute == null) {
- Slog.w(TAG, "addActiveRoute: btRoute is null");
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "Adding active route: " + btRoute.mRoute);
- }
- if (mActiveRoutes.contains(btRoute)) {
- Slog.w(TAG, "addActiveRoute: btRoute is already added.");
- return;
- }
- setRouteConnectionState(btRoute, STATE_CONNECTED);
- mActiveRoutes.add(btRoute);
- }
-
- private void removeActiveRoute(BluetoothRouteInfo btRoute) {
- if (DEBUG) {
- Log.d(TAG, "Removing active route: " + btRoute.mRoute);
- }
- if (mActiveRoutes.remove(btRoute)) {
- setRouteConnectionState(btRoute, STATE_DISCONNECTED);
- }
- }
-
- private void clearActiveRoutesWithType(int type) {
- if (DEBUG) {
- Log.d(TAG, "Clearing active routes with type. type=" + type);
- }
- Iterator<BluetoothRouteInfo> iter = mActiveRoutes.iterator();
- while (iter.hasNext()) {
- BluetoothRouteInfo btRoute = iter.next();
- if (btRoute.mRoute.getType() == type) {
- iter.remove();
- setRouteConnectionState(btRoute, STATE_DISCONNECTED);
- }
- }
- }
-
- private void addActiveDevices(BluetoothDevice device) {
- // Let the given device be the first active device
- BluetoothRouteInfo activeBtRoute = mBluetoothRoutes.get(device.getAddress());
- // This could happen if ACTION_ACTIVE_DEVICE_CHANGED is sent before
- // ACTION_CONNECTION_STATE_CHANGED is sent.
- if (activeBtRoute == null) {
- activeBtRoute = createBluetoothRoute(device);
- mBluetoothRoutes.put(device.getAddress(), activeBtRoute);
- }
- addActiveRoute(activeBtRoute);
-
- // A bluetooth route with the same route ID should be added.
- for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
- if (TextUtils.equals(btRoute.mRoute.getId(), activeBtRoute.mRoute.getId())
- && !TextUtils.equals(btRoute.mBtDevice.getAddress(),
- activeBtRoute.mBtDevice.getAddress())) {
- addActiveRoute(btRoute);
- }
- }
- }
-
private static class BluetoothRouteInfo {
private BluetoothDevice mBtDevice;
private MediaRoute2Info mRoute;
@@ -437,71 +439,25 @@
}
}
- // These callbacks run on the main thread.
- private final class BluetoothProfileListener implements BluetoothProfile.ServiceListener {
- @Override
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- List<BluetoothDevice> activeDevices;
- switch (profile) {
- case BluetoothProfile.A2DP:
- mA2dpProfile = (BluetoothA2dp) proxy;
- // It may contain null.
- activeDevices = mBluetoothAdapter.getActiveDevices(BluetoothProfile.A2DP);
- break;
- case BluetoothProfile.HEARING_AID:
- mHearingAidProfile = (BluetoothHearingAid) proxy;
- activeDevices = mBluetoothAdapter.getActiveDevices(
- BluetoothProfile.HEARING_AID);
- break;
- case BluetoothProfile.LE_AUDIO:
- mLeAudioProfile = (BluetoothLeAudio) proxy;
- activeDevices = mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
- break;
- default:
- return;
- }
- for (BluetoothDevice device : proxy.getConnectedDevices()) {
- BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
- if (btRoute == null) {
- btRoute = createBluetoothRoute(device);
- mBluetoothRoutes.put(device.getAddress(), btRoute);
- }
- if (activeDevices.contains(device)) {
- addActiveRoute(btRoute);
- }
- }
- notifyBluetoothRoutesUpdated();
- }
-
- @Override
- public void onServiceDisconnected(int profile) {
- switch (profile) {
- case BluetoothProfile.A2DP:
- mA2dpProfile = null;
- break;
- case BluetoothProfile.HEARING_AID:
- mHearingAidProfile = null;
- break;
- case BluetoothProfile.LE_AUDIO:
- mLeAudioProfile = null;
- break;
- default:
- return;
- }
- }
- }
-
private class AdapterStateChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
if (state == BluetoothAdapter.STATE_OFF
|| state == BluetoothAdapter.STATE_TURNING_OFF) {
- mBluetoothRoutes.clear();
+ synchronized (AudioPoliciesBluetoothRouteController.this) {
+ mBluetoothRoutes.clear();
+ }
notifyBluetoothRoutesUpdated();
} else if (state == BluetoothAdapter.STATE_ON) {
- buildBluetoothRoutes();
- if (!mBluetoothRoutes.isEmpty()) {
+ updateBluetoothRoutes();
+
+ boolean shouldCallListener;
+ synchronized (AudioPoliciesBluetoothRouteController.this) {
+ shouldCallListener = !mBluetoothRoutes.isEmpty();
+ }
+
+ if (shouldCallListener) {
notifyBluetoothRoutesUpdated();
}
}
@@ -511,74 +467,15 @@
private class DeviceStateChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- BluetoothDevice device = intent.getParcelableExtra(
- BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class);
-
switch (intent.getAction()) {
case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
- clearActiveRoutesWithType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP);
- if (device != null) {
- addActiveRoute(mBluetoothRoutes.get(device.getAddress()));
- }
- notifyBluetoothRoutesUpdated();
- break;
case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
- clearActiveRoutesWithType(MediaRoute2Info.TYPE_HEARING_AID);
- if (device != null) {
- if (DEBUG) {
- Log.d(TAG, "Setting active hearing aid devices. device=" + device);
- }
-
- addActiveDevices(device);
- }
- notifyBluetoothRoutesUpdated();
- break;
case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
- clearActiveRoutesWithType(MediaRoute2Info.TYPE_BLE_HEADSET);
- if (device != null) {
- if (DEBUG) {
- Log.d(TAG, "Setting active le audio devices. device=" + device);
- }
-
- addActiveDevices(device);
- }
- notifyBluetoothRoutesUpdated();
- break;
case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
- handleConnectionStateChanged(BluetoothProfile.A2DP, intent, device);
- break;
case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
- handleConnectionStateChanged(BluetoothProfile.HEARING_AID, intent, device);
- break;
case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
- handleConnectionStateChanged(BluetoothProfile.LE_AUDIO, intent, device);
- break;
- }
- }
-
- private void handleConnectionStateChanged(int profile, Intent intent,
- BluetoothDevice device) {
- int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
- BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
- if (state == BluetoothProfile.STATE_CONNECTED) {
- if (btRoute == null) {
- btRoute = createBluetoothRoute(device);
- if (btRoute.mConnectedProfiles.size() > 0) {
- mBluetoothRoutes.put(device.getAddress(), btRoute);
- notifyBluetoothRoutesUpdated();
- }
- } else {
- btRoute.mConnectedProfiles.put(profile, true);
- }
- } else if (state == BluetoothProfile.STATE_DISCONNECTING
- || state == BluetoothProfile.STATE_DISCONNECTED) {
- if (btRoute != null) {
- btRoute.mConnectedProfiles.delete(profile);
- if (btRoute.mConnectedProfiles.size() == 0) {
- removeActiveRoute(mBluetoothRoutes.remove(device.getAddress()));
- notifyBluetoothRoutesUpdated();
- }
- }
+ updateBluetoothRoutes();
+ notifyBluetoothRoutesUpdated();
}
}
}
diff --git a/services/core/java/com/android/server/media/BluetoothProfileMonitor.java b/services/core/java/com/android/server/media/BluetoothProfileMonitor.java
new file mode 100644
index 0000000..b129dd0
--- /dev/null
+++ b/services/core/java/com/android/server/media/BluetoothProfileMonitor.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import java.util.Objects;
+
+/* package */ class BluetoothProfileMonitor {
+
+ /* package */ static final long GROUP_ID_NO_GROUP = -1L;
+
+ @NonNull
+ private final ProfileListener mProfileListener = new ProfileListener();
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final BluetoothAdapter mBluetoothAdapter;
+
+ @Nullable
+ private BluetoothA2dp mA2dpProfile;
+ @Nullable
+ private BluetoothHearingAid mHearingAidProfile;
+ @Nullable
+ private BluetoothLeAudio mLeAudioProfile;
+
+ @Nullable
+ private OnProfileChangedListener mOnProfileChangedListener;
+
+ BluetoothProfileMonitor(@NonNull Context context,
+ @NonNull BluetoothAdapter bluetoothAdapter) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(bluetoothAdapter);
+
+ mContext = context;
+ mBluetoothAdapter = bluetoothAdapter;
+ }
+
+ /* package */ synchronized void setOnProfileChangedListener(
+ @NonNull OnProfileChangedListener listener) {
+ mOnProfileChangedListener = listener;
+ }
+
+ /* package */ void start() {
+ mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
+ mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
+ mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
+ }
+
+ /* package */ boolean isProfileSupported(int profile, @NonNull BluetoothDevice device) {
+ BluetoothProfile bluetoothProfile;
+
+ synchronized (this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ bluetoothProfile = mA2dpProfile;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ bluetoothProfile = mLeAudioProfile;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ bluetoothProfile = mHearingAidProfile;
+ break;
+ default:
+ throw new IllegalArgumentException(profile
+ + " is not supported as Bluetooth profile");
+ }
+ }
+
+ if (bluetoothProfile == null) {
+ return false;
+ }
+
+ return bluetoothProfile.getConnectedDevices().contains(device);
+ }
+
+ /* package */ long getGroupId(int profile, @NonNull BluetoothDevice device) {
+ synchronized (this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ return GROUP_ID_NO_GROUP;
+ case BluetoothProfile.LE_AUDIO:
+ return mLeAudioProfile == null ? GROUP_ID_NO_GROUP : mLeAudioProfile.getGroupId(
+ device);
+ case BluetoothProfile.HEARING_AID:
+ return mHearingAidProfile == null
+ ? GROUP_ID_NO_GROUP : mHearingAidProfile.getHiSyncId(device);
+ default:
+ throw new IllegalArgumentException(profile
+ + " is not supported as Bluetooth profile");
+ }
+ }
+ }
+
+ /* package */ interface OnProfileChangedListener {
+ void onProfileChange(int profile);
+ }
+
+ private final class ProfileListener implements BluetoothProfile.ServiceListener {
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ OnProfileChangedListener listener;
+
+ synchronized (BluetoothProfileMonitor.this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ mA2dpProfile = (BluetoothA2dp) proxy;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mHearingAidProfile = (BluetoothHearingAid) proxy;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudioProfile = (BluetoothLeAudio) proxy;
+ break;
+ default:
+ return;
+ }
+
+ listener = mOnProfileChangedListener;
+ }
+
+ if (listener != null) {
+ listener.onProfileChange(profile);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ OnProfileChangedListener listener;
+
+ synchronized (BluetoothProfileMonitor.this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ mA2dpProfile = null;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mHearingAidProfile = null;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudioProfile = null;
+ break;
+ default:
+ return;
+ }
+
+ listener = mOnProfileChangedListener;
+ }
+
+ if (listener != null) {
+ listener.onProfileChange(profile);
+ }
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
new file mode 100644
index 0000000..723cda0
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import android.annotation.StringDef;
+import android.provider.DeviceConfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/* package */ class MediaFeatureFlagManager {
+
+ /**
+ * Namespace for media better together features.
+ */
+ private static final String NAMESPACE_MEDIA_BETTER_TOGETHER = "media_better_together";
+
+ @StringDef(prefix = "FEATURE_", value = {
+ FEATURE_IS_USING_LEGACY_BLUETOOTH_CONTROLLER
+ })
+ @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+ @Retention(RetentionPolicy.SOURCE)
+ /* package */ @interface MediaFeatureFlag {}
+
+ /**
+ * Whether to use old legacy implementation of BluetoothRouteController or new
+ * 'Audio Strategies'-aware controller.
+ */
+ /* package */ static final @MediaFeatureFlag String
+ FEATURE_IS_USING_LEGACY_BLUETOOTH_CONTROLLER =
+ "BluetoothRouteController__enable_legacy_bluetooth_routes_controller";
+
+ private static final MediaFeatureFlagManager sInstance = new MediaFeatureFlagManager();
+
+ private MediaFeatureFlagManager() {
+ // Empty to prevent instantiation.
+ }
+
+ /* package */ MediaFeatureFlagManager getInstance() {
+ return sInstance;
+ }
+
+ /**
+ * Returns a boolean value from {@link DeviceConfig} from the system_time namespace, or
+ * {@code defaultValue} if there is no explicit value set.
+ */
+ public boolean getBoolean(@MediaFeatureFlag String key, boolean defaultValue) {
+ return DeviceConfig.getBoolean(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
+ }
+}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 638e81a..6619e6c 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -60,7 +60,7 @@
private final UserHandle mUser;
private final DeviceRouteController mDeviceRouteController;
- private final BluetoothRouteController mBtRouteProvider;
+ private final BluetoothRouteController mBluetoothRouteController;
private String mSelectedRouteId;
// For apps without MODIFYING_AUDIO_ROUTING permission.
@@ -84,7 +84,7 @@
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mBtRouteProvider = BluetoothRouteController.createInstance(context, (routes) -> {
+ mBluetoothRouteController = BluetoothRouteController.createInstance(context, (routes) -> {
publishProviderState();
if (updateSessionInfosIfNeeded()) {
notifySessionInfoUpdated();
@@ -113,7 +113,7 @@
intentFilter, null, null);
mHandler.post(() -> {
- mBtRouteProvider.start(mUser);
+ mBluetoothRouteController.start(mUser);
notifyProviderState();
});
updateVolume();
@@ -122,7 +122,7 @@
public void stop() {
mContext.unregisterReceiver(mAudioReceiver);
mHandler.post(() -> {
- mBtRouteProvider.stop();
+ mBluetoothRouteController.stop();
notifyProviderState();
});
}
@@ -189,9 +189,9 @@
MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
if (TextUtils.equals(routeId, deviceRoute.getId())) {
- mBtRouteProvider.transferTo(null);
+ mBluetoothRouteController.transferTo(null);
} else {
- mBtRouteProvider.transferTo(routeId);
+ mBluetoothRouteController.transferTo(routeId);
}
}
@@ -232,7 +232,7 @@
RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
SYSTEM_SESSION_ID, packageName).setSystemSession(true);
builder.addSelectedRoute(deviceRoute.getId());
- for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
+ for (MediaRoute2Info route : mBluetoothRouteController.getAllBluetoothRoutes()) {
builder.addTransferableRoute(route.getId());
}
return builder.setProviderId(mUniqueId).build();
@@ -245,7 +245,7 @@
// We must have a device route in the provider info.
builder.addRoute(mDeviceRouteController.getDeviceRoute());
- for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
+ for (MediaRoute2Info route : mBluetoothRouteController.getAllBluetoothRoutes()) {
builder.addRoute(route);
}
MediaRoute2ProviderInfo providerInfo = builder.build();
@@ -269,7 +269,7 @@
MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
MediaRoute2Info selectedRoute = deviceRoute;
- MediaRoute2Info selectedBtRoute = mBtRouteProvider.getSelectedRoute();
+ MediaRoute2Info selectedBtRoute = mBluetoothRouteController.getSelectedRoute();
if (selectedBtRoute != null) {
selectedRoute = selectedBtRoute;
builder.addTransferableRoute(deviceRoute.getId());
@@ -281,7 +281,7 @@
.build();
builder.addSelectedRoute(mSelectedRouteId);
- for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
+ for (MediaRoute2Info route : mBluetoothRouteController.getTransferableRoutes()) {
builder.addTransferableRoute(route.getId());
}
@@ -361,7 +361,7 @@
.build();
}
- if (mBtRouteProvider.updateVolumeForDevices(devices, volume)) {
+ if (mBluetoothRouteController.updateVolumeForDevices(devices, volume)) {
return;
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index c63cddd..59af58f 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -862,11 +862,11 @@
if (r == null) {
throw new IllegalArgumentException("Invalid package");
}
+ if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
+ throw new IllegalStateException("Limit exceed; cannot create more groups");
+ }
if (fromTargetApp) {
group.setBlocked(false);
- if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
- throw new IllegalStateException("Limit exceed; cannot create more groups");
- }
}
final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
if (oldGroup != null) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 4b2c88c..2774462 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -20,7 +20,7 @@
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
-import static android.service.notification.DNDModeProto.ROOT_CONFIG;
+import static android.service.notification.NotificationServiceProto.ROOT_CONFIG;
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index a789762..19575a3 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -675,10 +675,6 @@
@NonNull
UserInfo[] getUserInfos();
- boolean isChangeEnabled(long changeId, int uid);
-
- boolean isChangeEnabled(long changeId, ApplicationInfo info);
-
@NonNull
ArrayMap<String, ? extends SharedUserApi> getSharedUsers();
}
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index e28f1fc..14b72ff 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -125,7 +125,6 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.modules.utils.TypedXmlSerializer;
-import com.android.server.compat.PlatformCompat;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.PackageDexUsage;
@@ -575,7 +574,8 @@
list = new ArrayList<>(1);
list.add(ri);
PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
- this, list, false, intent, resolvedType, filterCallingUid);
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, intent, resolvedType, filterCallingUid);
}
}
} else {
@@ -591,7 +591,7 @@
String callingPkgName = getInstantAppPackageName(filterCallingUid);
boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
lockedResult.result = maybeAddInstantAppInstaller(
- lockedResult.result, intent, resolvedType, flags, filterCallingUid,
+ lockedResult.result, intent, resolvedType, flags,
userId, resolveForStart, isRequesterInstantApp);
}
if (lockedResult.sortResult) {
@@ -604,7 +604,8 @@
if (originalIntent != null) {
// We also have to ensure all components match the original intent
PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
- this, list, false, originalIntent, resolvedType, filterCallingUid);
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, originalIntent, resolvedType, filterCallingUid);
}
return skipPostResolution ? list : applyPostResolutionFilter(
@@ -686,7 +687,8 @@
list = new ArrayList<>(1);
list.add(ri);
PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
- this, list, false, intent, resolvedType, callingUid);
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, intent, resolvedType, callingUid);
}
}
} else {
@@ -697,7 +699,8 @@
if (originalIntent != null) {
// We also have to ensure all components match the original intent
PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
- this, list, false, originalIntent, resolvedType, callingUid);
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, originalIntent, resolvedType, callingUid);
}
return list;
@@ -710,7 +713,7 @@
String pkgName = intent.getPackage();
if (pkgName == null) {
final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
- resolvedType, flags, callingUid, userId);
+ resolvedType, flags, userId);
if (resolveInfos == null) {
return Collections.emptyList();
}
@@ -720,7 +723,7 @@
final AndroidPackage pkg = mPackages.get(pkgName);
if (pkg != null) {
final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
- resolvedType, flags, pkg.getServices(), callingUid,
+ resolvedType, flags, pkg.getServices(),
userId);
if (resolveInfos == null) {
return Collections.emptyList();
@@ -750,7 +753,7 @@
{@link PackageManager.SKIP_CURRENT_PROFILE} set.
*/
result.addAll(filterIfNotSystemUser(mComponentResolver.queryActivities(this,
- intent, resolvedType, flags, filterCallingUid, userId), userId));
+ intent, resolvedType, flags, userId), userId));
}
addInstant = isInstantAppResolutionAllowed(intent, result, userId,
false /*skipPackageCheck*/, flags);
@@ -774,7 +777,7 @@
|| !shouldFilterApplication(setting, filterCallingUid, userId))) {
result.addAll(filterIfNotSystemUser(mComponentResolver.queryActivities(this,
intent, resolvedType, flags, setting.getAndroidPackage().getActivities(),
- filterCallingUid, userId), userId));
+ userId), userId));
}
if (result == null || result.size() == 0) {
// the caller wants to resolve for a particular package; however, there
@@ -1105,7 +1108,7 @@
return null;
}
List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(this, intent,
- resolvedType, flags, Binder.getCallingUid(), parentUserId);
+ resolvedType, flags, parentUserId);
if (resultTargetUser == null || resultTargetUser.isEmpty()) {
return null;
@@ -1343,7 +1346,7 @@
private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result,
Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,
- int callingUid, int userId, boolean resolveForStart, boolean isRequesterInstantApp) {
+ int userId, boolean resolveForStart, boolean isRequesterInstantApp) {
// first, check to see if we've got an instant app already installed
final boolean alreadyResolvedLocally = (flags & PackageManager.MATCH_INSTANT) != 0;
ResolveInfo localInstantApp = null;
@@ -1356,7 +1359,6 @@
| PackageManager.GET_RESOLVED_FILTER
| PackageManager.MATCH_INSTANT
| PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY,
- callingUid,
userId);
for (int i = instantApps.size() - 1; i >= 0; --i) {
final ResolveInfo info = instantApps.get(i);
@@ -3691,13 +3693,10 @@
ps, callingUid, component, TYPE_ACTIVITY, userId, true /* filterUninstall */)) {
return false;
}
- final boolean callerBlocksNullAction = isChangeEnabled(
- IntentFilter.BLOCK_NULL_ACTION_INTENTS, callingUid);
for (int i=0; i< a.getIntents().size(); i++) {
if (a.getIntents().get(i).getIntentFilter()
.match(intent.getAction(), resolvedType, intent.getScheme(),
- intent.getData(), intent.getCategories(), TAG,
- /*supportWildcards*/ false, callerBlocksNullAction, null, null) >= 0) {
+ intent.getData(), intent.getCategories(), TAG) >= 0) {
return true;
}
}
@@ -5795,37 +5794,4 @@
public UserInfo[] getUserInfos() {
return mInjector.getUserManagerInternal().getUserInfos();
}
-
- @Override
- public boolean isChangeEnabled(long changeId, int uid) {
- final PlatformCompat compat = mInjector.getCompatibility();
- int appId = UserHandle.getAppId(uid);
- SettingBase s = mSettings.getSettingBase(appId);
- if (s instanceof PackageSetting) {
- var ps = (PackageSetting) s;
- if (ps.getAndroidPackage() == null) return false;
- var info = new ApplicationInfo();
- info.packageName = ps.getPackageName();
- info.targetSdkVersion = ps.getAndroidPackage().getTargetSdkVersion();
- return compat.isChangeEnabledInternal(changeId, info);
- } else if (s instanceof SharedUserSetting) {
- var ss = (SharedUserSetting) s;
- List<AndroidPackage> packages = ss.getPackages();
- for (int i = 0; i < packages.size(); ++i) {
- var pkg = packages.get(i);
- var info = new ApplicationInfo();
- info.packageName = pkg.getPackageName();
- info.targetSdkVersion = pkg.getTargetSdkVersion();
- if (compat.isChangeEnabledInternal(changeId, info)) {
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public boolean isChangeEnabled(long changeId, ApplicationInfo info) {
- return mInjector.getCompatibility().isChangeEnabledInternal(changeId, info);
- }
}
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java b/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
index ee8f560..90d89c6 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
@@ -23,7 +23,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
-import android.os.Binder;
import android.util.SparseBooleanArray;
import com.android.internal.app.IntentForwarderActivity;
@@ -279,7 +278,7 @@
}
List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(computer, intent,
- resolvedType, flags, Binder.getCallingUid(), targetUserId);
+ resolvedType, flags, targetUserId);
if (CollectionUtils.isEmpty(resultTargetUser)) {
return null;
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index a868470..7fe6c7d 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -164,6 +164,7 @@
import com.android.server.EventLogTags;
import com.android.server.LocalManagerRegistry;
import com.android.server.art.model.DexoptParams;
+import com.android.server.art.model.DexoptResult;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.DexManager;
@@ -2534,8 +2535,9 @@
packageManagerLocal.withFilteredSnapshot()) {
DexoptParams params =
dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
- DexOptHelper.getArtManagerLocal().dexoptPackage(
+ DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
snapshot, packageName, params);
+ installRequest.onDexoptFinished(dexOptResult);
}
} else {
try {
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 46ea010..95e7904 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -43,6 +43,7 @@
import android.util.ExceptionUtils;
import android.util.Slog;
+import com.android.server.art.model.DexoptResult;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
@@ -127,6 +128,8 @@
private final int mSessionId;
private final int mRequireUserAction;
+ private int mDexoptStatus;
+
// New install
InstallRequest(InstallingSession params) {
mUserId = params.getUser().getIdentifier();
@@ -609,6 +612,10 @@
return mRequireUserAction;
}
+ public int getDexoptStatus() {
+ return mDexoptStatus;
+ }
+
public void setScanFlags(int scanFlags) {
mScanFlags = scanFlags;
}
@@ -799,6 +806,25 @@
}
}
+ public void onDexoptFinished(DexoptResult dexoptResult) {
+ if (mPackageMetrics == null) {
+ return;
+ }
+ mDexoptStatus = dexoptResult.getFinalStatus();
+ if (mDexoptStatus != DexoptResult.DEXOPT_PERFORMED) {
+ return;
+ }
+ long durationMillis = 0;
+ for (DexoptResult.PackageDexoptResult packageResult :
+ dexoptResult.getPackageDexoptResults()) {
+ for (DexoptResult.DexContainerFileDexoptResult fileResult :
+ packageResult.getDexContainerFileDexoptResults()) {
+ durationMillis += fileResult.getDex2oatWallTimeMillis();
+ }
+ }
+ mPackageMetrics.onStepFinished(PackageMetrics.STEP_DEXOPT, durationMillis);
+ }
+
public void onInstallCompleted() {
if (getReturnCode() == INSTALL_SUCCEEDED) {
if (mPackageMetrics != null) {
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index e53e756..3923890 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -102,7 +102,7 @@
boolean hasNonNegativePriorityResult,
Function<String, PackageStateInternal> pkgSettingFunction) {
List<ResolveInfo> resolveInfos = mComponentResolver.queryActivities(computer,
- intent, resolvedType, flags, Binder.getCallingUid(), targetUserId);
+ intent, resolvedType, flags, targetUserId);
List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>();
if (resolveInfos != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 9036d4c..928ffa7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -16,7 +16,6 @@
package com.android.server.pm;
-import static android.content.IntentFilter.BLOCK_NULL_ACTION_INTENTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
@@ -95,6 +94,7 @@
import com.android.server.IntentResolver;
import com.android.server.LocalManagerRegistry;
import com.android.server.Watchdog;
+import com.android.server.compat.PlatformCompat;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
@@ -1166,8 +1166,10 @@
return (ps.getFlags() & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
+ // Static to give access to ComputeEngine
public static void applyEnforceIntentFilterMatching(
- Computer computer, List<ResolveInfo> resolveInfos, boolean isReceiver,
+ PlatformCompat compat, ComponentResolverApi resolver,
+ List<ResolveInfo> resolveInfos, boolean isReceiver,
Intent intent, String resolvedType, int filterCallingUid) {
if (DISABLE_ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS.get()) return;
@@ -1175,11 +1177,6 @@
? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM)
: null;
- final boolean callerBlocksNullAction = computer.isChangeEnabled(
- BLOCK_NULL_ACTION_INTENTS, filterCallingUid);
-
- final ComponentResolverApi resolver = computer.getComponentResolver();
-
for (int i = resolveInfos.size() - 1; i >= 0; --i) {
final ComponentInfo info = resolveInfos.get(i).getComponentInfo();
@@ -1190,15 +1187,11 @@
}
// Only enforce filter matching if target app's target SDK >= T
- if (!computer.isChangeEnabled(
+ if (!compat.isChangeEnabledInternal(
ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, info.applicationInfo)) {
continue;
}
- // Block null action intent if either source or target app's target SDK >= U
- final boolean blockNullAction = callerBlocksNullAction
- || computer.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS, info.applicationInfo);
-
final ParsedMainComponent comp;
if (info instanceof ActivityInfo) {
if (isReceiver) {
@@ -1220,8 +1213,7 @@
boolean match = false;
for (int j = 0, size = comp.getIntents().size(); j < size; ++j) {
IntentFilter intentFilter = comp.getIntents().get(j).getIntentFilter();
- if (IntentResolver.intentMatchesFilter(
- intentFilter, intent, resolvedType, blockNullAction)) {
+ if (IntentResolver.intentMatchesFilter(intentFilter, intent, resolvedType)) {
match = true;
break;
}
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index fe014a4..80d6ebb 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -48,12 +48,14 @@
public static final int STEP_SCAN = 2;
public static final int STEP_RECONCILE = 3;
public static final int STEP_COMMIT = 4;
+ public static final int STEP_DEXOPT = 5;
@IntDef(prefix = {"STEP_"}, value = {
STEP_PREPARE,
STEP_SCAN,
STEP_RECONCILE,
STEP_COMMIT,
+ STEP_DEXOPT
})
@Retention(RetentionPolicy.SOURCE)
public @interface StepInt {
@@ -175,6 +177,10 @@
}
}
+ public void onStepFinished(@StepInt int step, long durationMillis) {
+ mInstallSteps.put(step, new InstallStep(durationMillis));
+ }
+
// List of steps (e.g., 1, 2, 3) and corresponding list of durations (e.g., 200ms, 100ms, 150ms)
private Pair<int[], long[]> getInstallStepDurations() {
ArrayList<Integer> steps = new ArrayList<>();
@@ -203,6 +209,11 @@
mStartTimestampMillis = System.currentTimeMillis();
}
+ InstallStep(long durationMillis) {
+ mStartTimestampMillis = -1;
+ mDurationMillis = durationMillis;
+ }
+
void finish() {
mDurationMillis = System.currentTimeMillis() - mStartTimestampMillis;
}
diff --git a/services/core/java/com/android/server/pm/ResilientAtomicFile.java b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
new file mode 100644
index 0000000..19aa4f8
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2023 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.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.security.FileIntegrity;
+
+import libcore.io.IoUtils;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+final class ResilientAtomicFile implements Closeable {
+ private static final String LOG_TAG = "ResilientAtomicFile";
+
+ private final File mFile;
+
+ private final File mTemporaryBackup;
+
+ private final File mReserveCopy;
+
+ private final int mFileMode;
+
+ private final String mDebugName;
+
+ private final ReadEventLogger mReadEventLogger;
+
+ // Write state.
+ private FileOutputStream mMainOutStream = null;
+ private FileInputStream mMainInStream = null;
+ private FileOutputStream mReserveOutStream = null;
+ private FileInputStream mReserveInStream = null;
+
+ // Read state.
+ private File mCurrentFile = null;
+ private FileInputStream mCurrentInStream = null;
+
+ private void finalizeOutStream(FileOutputStream str) throws IOException {
+ // Flash/sync + set permissions.
+ str.flush();
+ FileUtils.sync(str);
+ FileUtils.setPermissions(str.getFD(), mFileMode, -1, -1);
+ }
+
+ ResilientAtomicFile(@NonNull File file, @NonNull File temporaryBackup,
+ @NonNull File reserveCopy, int fileMode, String debugName,
+ @Nullable ReadEventLogger readEventLogger) {
+ mFile = file;
+ mTemporaryBackup = temporaryBackup;
+ mReserveCopy = reserveCopy;
+ mFileMode = fileMode;
+ mDebugName = debugName;
+ mReadEventLogger = readEventLogger;
+ }
+
+ public File getBaseFile() {
+ return mFile;
+ }
+
+ public FileOutputStream startWrite() throws IOException {
+ if (mMainOutStream != null) {
+ throw new IllegalStateException("Duplicate startWrite call?");
+ }
+
+ new File(mFile.getParent()).mkdirs();
+
+ if (mFile.exists()) {
+ // Presence of backup settings file indicates that we failed
+ // to persist packages earlier. So preserve the older
+ // backup for future reference since the current packages
+ // might have been corrupted.
+ if (!mTemporaryBackup.exists()) {
+ if (!mFile.renameTo(mTemporaryBackup)) {
+ throw new IOException("Unable to backup " + mDebugName
+ + " file, current changes will be lost at reboot");
+ }
+ } else {
+ mFile.delete();
+ Slog.w(LOG_TAG, "Preserving older " + mDebugName + " backup");
+ }
+ }
+ // Reserve copy is not valid anymore.
+ mReserveCopy.delete();
+
+ // In case of MT access, it's possible the files get overwritten during write.
+ // Let's open all FDs we need now.
+ mMainOutStream = new FileOutputStream(mFile);
+ mMainInStream = new FileInputStream(mFile);
+ mReserveOutStream = new FileOutputStream(mReserveCopy);
+ mReserveInStream = new FileInputStream(mReserveCopy);
+
+ return mMainOutStream;
+ }
+
+ public void finishWrite(FileOutputStream str) throws IOException {
+ if (mMainOutStream != str) {
+ throw new IllegalStateException("Invalid incoming stream.");
+ }
+
+ // Flush and set permissions.
+ try (FileOutputStream mainOutStream = mMainOutStream) {
+ mMainOutStream = null;
+ finalizeOutStream(mainOutStream);
+ }
+ // New file successfully written, old one are no longer needed.
+ mTemporaryBackup.delete();
+
+ try (FileInputStream mainInStream = mMainInStream;
+ FileInputStream reserveInStream = mReserveInStream) {
+ mMainInStream = null;
+ mReserveInStream = null;
+
+ // Copy main file to reserve.
+ try (FileOutputStream reserveOutStream = mReserveOutStream) {
+ mReserveOutStream = null;
+ FileUtils.copy(mainInStream, reserveOutStream);
+ finalizeOutStream(reserveOutStream);
+ }
+
+ // Protect both main and reserve using fs-verity.
+ try (ParcelFileDescriptor mainPfd = ParcelFileDescriptor.dup(mainInStream.getFD());
+ ParcelFileDescriptor copyPfd = ParcelFileDescriptor.dup(reserveInStream.getFD())) {
+ FileIntegrity.setUpFsVerity(mainPfd);
+ FileIntegrity.setUpFsVerity(copyPfd);
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Failed to verity-protect " + mDebugName, e);
+ }
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Failed to write reserve copy " + mDebugName + ": " + mReserveCopy, e);
+ }
+ }
+
+ public void failWrite(FileOutputStream str) {
+ if (mMainOutStream != str) {
+ throw new IllegalStateException("Invalid incoming stream.");
+ }
+
+ // Close all FDs.
+ close();
+
+ // Clean up partially written files
+ if (mFile.exists()) {
+ if (!mFile.delete()) {
+ Slog.i(LOG_TAG, "Failed to clean up mangled file: " + mFile);
+ }
+ }
+ }
+
+ public FileInputStream openRead() throws IOException {
+ if (mTemporaryBackup.exists()) {
+ try {
+ mCurrentFile = mTemporaryBackup;
+ mCurrentInStream = new FileInputStream(mCurrentFile);
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.INFO,
+ "Need to read from backup " + mDebugName + " file");
+ }
+ if (mFile.exists()) {
+ // If both the backup and normal file exist, we
+ // ignore the normal one since it might have been
+ // corrupted.
+ Slog.w(LOG_TAG, "Cleaning up " + mDebugName + " file " + mFile);
+ mFile.delete();
+ }
+ // Ignore reserve copy as well.
+ mReserveCopy.delete();
+ } catch (java.io.IOException e) {
+ // We'll try for the normal settings file.
+ }
+ }
+
+ if (mCurrentInStream != null) {
+ return mCurrentInStream;
+ }
+
+ if (mFile.exists()) {
+ mCurrentFile = mFile;
+ mCurrentInStream = new FileInputStream(mCurrentFile);
+ } else if (mReserveCopy.exists()) {
+ mCurrentFile = mReserveCopy;
+ mCurrentInStream = new FileInputStream(mCurrentFile);
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.INFO,
+ "Need to read from reserve copy " + mDebugName + " file");
+ }
+ }
+
+ if (mCurrentInStream == null) {
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.INFO, "No " + mDebugName + " file");
+ }
+ }
+
+ return mCurrentInStream;
+ }
+
+ public void failRead(FileInputStream str, Exception e) {
+ if (mCurrentInStream != str) {
+ throw new IllegalStateException("Invalid incoming stream.");
+ }
+ mCurrentInStream = null;
+ IoUtils.closeQuietly(str);
+
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.ERROR,
+ "Error reading " + mDebugName + ", removing " + mCurrentFile + '\n'
+ + Log.getStackTraceString(e));
+ }
+
+ mCurrentFile.delete();
+ mCurrentFile = null;
+ }
+
+ public void delete() {
+ mFile.delete();
+ mTemporaryBackup.delete();
+ mReserveCopy.delete();
+ }
+
+ @Override
+ public void close() {
+ IoUtils.closeQuietly(mMainOutStream);
+ IoUtils.closeQuietly(mMainInStream);
+ IoUtils.closeQuietly(mReserveOutStream);
+ IoUtils.closeQuietly(mReserveInStream);
+ IoUtils.closeQuietly(mCurrentInStream);
+ mMainOutStream = null;
+ mMainInStream = null;
+ mReserveOutStream = null;
+ mReserveInStream = null;
+ mCurrentInStream = null;
+ mCurrentFile = null;
+ }
+
+ public String toString() {
+ return mFile.getPath();
+ }
+
+ interface ReadEventLogger {
+ void logEvent(int priority, String msg);
+ }
+}
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index 8bca4a9..a13c568 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -466,14 +466,15 @@
list = new ArrayList<>(1);
list.add(ri);
PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
- computer, list, true, intent, resolvedType, filterCallingUid);
+ mPlatformCompat, componentResolver, list, true, intent,
+ resolvedType, filterCallingUid);
}
}
} else {
String pkgName = intent.getPackage();
if (pkgName == null) {
- final List<ResolveInfo> result = componentResolver.queryReceivers(
- computer, intent, resolvedType, flags, filterCallingUid, userId);
+ final List<ResolveInfo> result = componentResolver
+ .queryReceivers(computer, intent, resolvedType, flags, userId);
if (result != null) {
list = result;
}
@@ -481,7 +482,7 @@
final AndroidPackage pkg = computer.getPackage(pkgName);
if (pkg != null) {
final List<ResolveInfo> result = componentResolver.queryReceivers(computer,
- intent, resolvedType, flags, pkg.getReceivers(), filterCallingUid, userId);
+ intent, resolvedType, flags, pkg.getReceivers(), userId);
if (result != null) {
list = result;
}
@@ -491,7 +492,8 @@
if (originalIntent != null) {
// We also have to ensure all components match the original intent
PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
- computer, list, true, originalIntent, resolvedType, filterCallingUid);
+ mPlatformCompat, componentResolver,
+ list, true, originalIntent, resolvedType, filterCallingUid);
}
return computer.applyPostResolutionFilter(list, instantAppPkgName, false, queryingUid,
@@ -575,7 +577,7 @@
String pkgName = intent.getPackage();
if (pkgName == null) {
final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
- intent, resolvedType, flags, callingUid, userId);
+ intent, resolvedType, flags, userId);
if (resolveInfos == null) {
return Collections.emptyList();
}
@@ -585,7 +587,7 @@
final AndroidPackage pkg = computer.getPackage(pkgName);
if (pkg != null) {
final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
- intent, resolvedType, flags, pkg.getProviders(), callingUid, userId);
+ intent, resolvedType, flags, pkg.getProviders(), userId);
if (resolveInfos == null) {
return Collections.emptyList();
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 70ca17f..4675a7c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -120,7 +120,6 @@
import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationPersistence;
-import com.android.server.security.FileIntegrity;
import com.android.server.utils.Slogf;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
@@ -173,7 +172,7 @@
/**
* Holds information about dynamic settings.
*/
-public final class Settings implements Watchable, Snappable {
+public final class Settings implements Watchable, Snappable, ResilientAtomicFile.ReadEventLogger {
private static final String TAG = "PackageSettings";
/**
@@ -345,7 +344,7 @@
private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
private static final String ATTR_ENABLED = "enabled";
private static final String ATTR_ENABLED_CALLER = "enabledCaller";
- private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
+ private static final String ATTR_DOMAIN_VERIFICATION_STATE = "domainVerificationStatus";
private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
private static final String ATTR_INSTALL_REASON = "install-reason";
private static final String ATTR_UNINSTALL_REASON = "uninstall-reason";
@@ -1516,16 +1515,22 @@
return new File(new File(mSystemDir, "users"), Integer.toString(userId));
}
- // The method itself does not have to be guarded, but the file does.
- @GuardedBy("mPackageRestrictionsLock")
- private File getUserPackagesStateFile(int userId) {
- return new File(getUserSystemDirectory(userId), "package-restrictions.xml");
+ private ResilientAtomicFile getUserPackagesStateFile(int userId) {
+ File mainFile = new File(getUserSystemDirectory(userId), "package-restrictions.xml");
+ File temporaryBackup = new File(getUserSystemDirectory(userId),
+ "package-restrictions-backup.xml");
+ File reserveCopy = new File(getUserSystemDirectory(userId),
+ "package-restrictions.xml.reservecopy");
+ return new ResilientAtomicFile(mainFile, temporaryBackup, reserveCopy,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ "package restrictions", this);
}
- // The method itself does not have to be guarded, but the file does.
- @GuardedBy("mPackageRestrictionsLock")
- private File getUserPackagesStateBackupFile(int userId) {
- return new File(getUserSystemDirectory(userId), "package-restrictions-backup.xml");
+ private ResilientAtomicFile getSettingsFile() {
+ return new ResilientAtomicFile(mSettingsFilename, mPreviousSettingsFilename,
+ mSettingsReserveCopyFilename,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ "package manager settings", this);
}
private File getUserRuntimePermissionsFile(int userId) {
@@ -1735,272 +1740,243 @@
}
}
+ @Override
+ public void logEvent(int priority, String msg) {
+ mReadMessages.append(msg + "\n");
+ PackageManagerService.reportSettingsProblem(priority, msg);
+ }
+
+
void readPackageRestrictionsLPr(int userId,
@NonNull ArrayMap<String, Long> origFirstInstallTimes) {
if (DEBUG_MU) {
Log.i(TAG, "Reading package restrictions for user=" + userId);
}
- FileInputStream str = null;
- synchronized (mPackageRestrictionsLock) {
- File userPackagesStateFile = getUserPackagesStateFile(userId);
- File backupFile = getUserPackagesStateBackupFile(userId);
- if (backupFile.exists()) {
- try {
- str = new FileInputStream(backupFile);
- mReadMessages.append("Reading from backup stopped packages file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "Need to read from backup stopped packages file");
- if (userPackagesStateFile.exists()) {
- // If both the backup and normal file exist, we
- // ignore the normal one since it might have been
- // corrupted.
- Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
- + userPackagesStateFile);
- userPackagesStateFile.delete();
+ try (ResilientAtomicFile atomicFile = getUserPackagesStateFile(userId)) {
+ FileInputStream str = null;
+ try {
+ synchronized (mPackageRestrictionsLock) {
+ str = atomicFile.openRead();
+ if (str == null) {
+ // At first boot, make sure no packages are stopped.
+ // We usually want to have third party apps initialize
+ // in the stopped state, but not at first boot. Also
+ // consider all applications to be installed.
+ for (PackageSetting pkg : mPackages.values()) {
+ pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
+ true /*installed*/,
+ false /*stopped*/,
+ false /*notLaunched*/,
+ false /*hidden*/,
+ 0 /*distractionFlags*/,
+ null /*suspendParams*/,
+ false /*instantApp*/,
+ false /*virtualPreload*/,
+ null /*lastDisableAppCaller*/,
+ null /*enabledComponents*/,
+ null /*disabledComponents*/,
+ PackageManager.INSTALL_REASON_UNKNOWN,
+ PackageManager.UNINSTALL_REASON_UNKNOWN,
+ null /*harmfulAppWarning*/,
+ null /* splashScreenTheme*/,
+ 0 /*firstInstallTime*/
+ );
+ }
+ return;
}
- } catch (java.io.IOException e) {
- // We'll try for the normal settings file.
- }
- }
-
- if (str == null && userPackagesStateFile.exists()) {
- try {
- str = new FileInputStream(userPackagesStateFile);
- if (DEBUG_MU) Log.i(TAG, "Reading " + userPackagesStateFile);
- } catch (java.io.IOException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR,
- "Error reading settings: " + e);
- Slog.wtf(TAG, "Error reading package manager stopped packages", e);
- }
- }
- }
-
- if (str == null) {
- mReadMessages.append("No stopped packages file found\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "No stopped packages file; "
- + "assuming all started");
- // At first boot, make sure no packages are stopped.
- // We usually want to have third party apps initialize
- // in the stopped state, but not at first boot. Also
- // consider all applications to be installed.
- for (PackageSetting pkg : mPackages.values()) {
- pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
- true /*installed*/,
- false /*stopped*/,
- false /*notLaunched*/,
- false /*hidden*/,
- 0 /*distractionFlags*/,
- null /*suspendParams*/,
- false /*instantApp*/,
- false /*virtualPreload*/,
- null /*lastDisableAppCaller*/,
- null /*enabledComponents*/,
- null /*disabledComponents*/,
- PackageManager.INSTALL_REASON_UNKNOWN,
- PackageManager.UNINSTALL_REASON_UNKNOWN,
- null /*harmfulAppWarning*/,
- null /* splashScreenTheme*/,
- 0 /*firstInstallTime*/
- );
- }
- return;
- }
-
- try {
- final TypedXmlPullParser parser = Xml.resolvePullParser(str);
-
- int type;
- while ((type=parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- ;
- }
-
- if (type != XmlPullParser.START_TAG) {
- mReadMessages.append("No start tag found in package restrictions file\n");
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "No start tag found in package manager stopped packages");
- return;
- }
-
- int outerDepth = parser.getDepth();
- PackageSetting ps = null;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
- continue;
}
- String tagName = parser.getName();
- if (tagName.equals(TAG_PACKAGE)) {
- String name = parser.getAttributeValue(null, ATTR_NAME);
- ps = mPackages.get(name);
- if (ps == null) {
- Slog.w(PackageManagerService.TAG, "No package known for stopped package "
- + name);
- XmlUtils.skipCurrentTag(parser);
+ final TypedXmlPullParser parser = Xml.resolvePullParser(str);
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // nothing
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ mReadMessages.append("No start tag found in package restrictions file\n");
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "No start tag found in package manager package restrictions file");
+ return;
+ }
+
+ int outerDepth = parser.getDepth();
+ PackageSetting ps = null;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
continue;
}
- final long ceDataInode =
- parser.getAttributeLong(null, ATTR_CE_DATA_INODE, 0);
- final boolean installed =
- parser.getAttributeBoolean(null, ATTR_INSTALLED, true);
- final boolean stopped =
- parser.getAttributeBoolean(null, ATTR_STOPPED, false);
- final boolean notLaunched =
- parser.getAttributeBoolean(null, ATTR_NOT_LAUNCHED, false);
-
- // For backwards compatibility with the previous name of "blocked", which
- // now means hidden, read the old attribute as well.
- boolean hidden = parser.getAttributeBoolean(null, ATTR_HIDDEN, false);
- if (!hidden) {
- hidden = parser.getAttributeBoolean(null, ATTR_BLOCKED, false);
- }
-
- final int distractionFlags = parser.getAttributeInt(null, ATTR_DISTRACTION_FLAGS, 0);
- final boolean suspended = parser.getAttributeBoolean(null, ATTR_SUSPENDED, false);
- String oldSuspendingPackage = parser.getAttributeValue(null,
- ATTR_SUSPENDING_PACKAGE);
- final String dialogMessage = parser.getAttributeValue(null,
- ATTR_SUSPEND_DIALOG_MESSAGE);
- if (suspended && oldSuspendingPackage == null) {
- oldSuspendingPackage = PLATFORM_PACKAGE_NAME;
- }
-
- final boolean blockUninstall =
- parser.getAttributeBoolean(null, ATTR_BLOCK_UNINSTALL, false);
- final boolean instantApp =
- parser.getAttributeBoolean(null, ATTR_INSTANT_APP, false);
- final boolean virtualPreload =
- parser.getAttributeBoolean(null, ATTR_VIRTUAL_PRELOAD, false);
- final int enabled = parser.getAttributeInt(null, ATTR_ENABLED,
- COMPONENT_ENABLED_STATE_DEFAULT);
- final String enabledCaller = parser.getAttributeValue(null,
- ATTR_ENABLED_CALLER);
- final String harmfulAppWarning =
- parser.getAttributeValue(null, ATTR_HARMFUL_APP_WARNING);
- final int verifState = parser.getAttributeInt(null,
- ATTR_DOMAIN_VERIFICATON_STATE,
- PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
- final int installReason = parser.getAttributeInt(null, ATTR_INSTALL_REASON,
- PackageManager.INSTALL_REASON_UNKNOWN);
- final int uninstallReason = parser.getAttributeInt(null, ATTR_UNINSTALL_REASON,
- PackageManager.UNINSTALL_REASON_UNKNOWN);
- final String splashScreenTheme = parser.getAttributeValue(null,
- ATTR_SPLASH_SCREEN_THEME);
- final long firstInstallTime = parser.getAttributeLongHex(null,
- ATTR_FIRST_INSTALL_TIME, 0);
-
- ArraySet<String> enabledComponents = null;
- ArraySet<String> disabledComponents = null;
- PersistableBundle suspendedAppExtras = null;
- PersistableBundle suspendedLauncherExtras = null;
- SuspendDialogInfo oldSuspendDialogInfo = null;
-
- int packageDepth = parser.getDepth();
- ArrayMap<String, SuspendParams> suspendParamsMap = null;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > packageDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
+ String tagName = parser.getName();
+ if (tagName.equals(TAG_PACKAGE)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ ps = mPackages.get(name);
+ if (ps == null) {
+ Slog.w(PackageManagerService.TAG,
+ "No package known for package restrictions " + name);
+ XmlUtils.skipCurrentTag(parser);
continue;
}
- switch (parser.getName()) {
- case TAG_ENABLED_COMPONENTS:
- enabledComponents = readComponentsLPr(parser);
- break;
- case TAG_DISABLED_COMPONENTS:
- disabledComponents = readComponentsLPr(parser);
- break;
- case TAG_SUSPENDED_APP_EXTRAS:
- suspendedAppExtras = PersistableBundle.restoreFromXml(parser);
- break;
- case TAG_SUSPENDED_LAUNCHER_EXTRAS:
- suspendedLauncherExtras = PersistableBundle.restoreFromXml(parser);
- break;
- case TAG_SUSPENDED_DIALOG_INFO:
- oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
- break;
- case TAG_SUSPEND_PARAMS:
- final String suspendingPackage = parser.getAttributeValue(null,
- ATTR_SUSPENDING_PACKAGE);
- if (suspendingPackage == null) {
- Slog.wtf(TAG, "No suspendingPackage found inside tag "
- + TAG_SUSPEND_PARAMS);
- continue;
- }
- if (suspendParamsMap == null) {
- suspendParamsMap = new ArrayMap<>();
- }
- suspendParamsMap.put(suspendingPackage,
- SuspendParams.restoreFromXml(parser));
- break;
- default:
- Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
- + TAG_PACKAGE);
+
+ final long ceDataInode =
+ parser.getAttributeLong(null, ATTR_CE_DATA_INODE, 0);
+ final boolean installed =
+ parser.getAttributeBoolean(null, ATTR_INSTALLED, true);
+ final boolean stopped =
+ parser.getAttributeBoolean(null, ATTR_STOPPED, false);
+ final boolean notLaunched =
+ parser.getAttributeBoolean(null, ATTR_NOT_LAUNCHED, false);
+
+ // For backwards compatibility with the previous name of "blocked", which
+ // now means hidden, read the old attribute as well.
+ boolean hidden = parser.getAttributeBoolean(null, ATTR_HIDDEN, false);
+ if (!hidden) {
+ hidden = parser.getAttributeBoolean(null, ATTR_BLOCKED, false);
}
- }
- if (oldSuspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
- oldSuspendDialogInfo = new SuspendDialogInfo.Builder()
- .setMessage(dialogMessage)
- .build();
- }
- if (suspended && suspendParamsMap == null) {
- final SuspendParams suspendParams = new SuspendParams(
- oldSuspendDialogInfo,
- suspendedAppExtras,
- suspendedLauncherExtras);
- suspendParamsMap = new ArrayMap<>();
- suspendParamsMap.put(oldSuspendingPackage, suspendParams);
- }
- if (blockUninstall) {
- setBlockUninstallLPw(userId, name, true);
- }
- ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
- hidden, distractionFlags, suspendParamsMap, instantApp, virtualPreload,
- enabledCaller, enabledComponents, disabledComponents, installReason,
- uninstallReason, harmfulAppWarning, splashScreenTheme,
- firstInstallTime != 0 ? firstInstallTime :
- origFirstInstallTimes.getOrDefault(name, 0L));
+ final int distractionFlags = parser.getAttributeInt(null,
+ ATTR_DISTRACTION_FLAGS, 0);
+ final boolean suspended = parser.getAttributeBoolean(null, ATTR_SUSPENDED,
+ false);
+ String oldSuspendingPackage = parser.getAttributeValue(null,
+ ATTR_SUSPENDING_PACKAGE);
+ final String dialogMessage = parser.getAttributeValue(null,
+ ATTR_SUSPEND_DIALOG_MESSAGE);
+ if (suspended && oldSuspendingPackage == null) {
+ oldSuspendingPackage = PLATFORM_PACKAGE_NAME;
+ }
- mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
- } else if (tagName.equals("preferred-activities")) {
- readPreferredActivitiesLPw(parser, userId);
- } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
- readPersistentPreferredActivitiesLPw(parser, userId);
- } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
- readCrossProfileIntentFiltersLPw(parser, userId);
- } else if (tagName.equals(TAG_DEFAULT_APPS)) {
- readDefaultAppsLPw(parser, userId);
- } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
- readBlockUninstallPackagesLPw(parser, userId);
- } else {
- Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
+ final boolean blockUninstall =
+ parser.getAttributeBoolean(null, ATTR_BLOCK_UNINSTALL, false);
+ final boolean instantApp =
+ parser.getAttributeBoolean(null, ATTR_INSTANT_APP, false);
+ final boolean virtualPreload =
+ parser.getAttributeBoolean(null, ATTR_VIRTUAL_PRELOAD, false);
+ final int enabled = parser.getAttributeInt(null, ATTR_ENABLED,
+ COMPONENT_ENABLED_STATE_DEFAULT);
+ final String enabledCaller = parser.getAttributeValue(null,
+ ATTR_ENABLED_CALLER);
+ final String harmfulAppWarning =
+ parser.getAttributeValue(null, ATTR_HARMFUL_APP_WARNING);
+ final int verifState = parser.getAttributeInt(null,
+ ATTR_DOMAIN_VERIFICATION_STATE,
+ PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
+ final int installReason = parser.getAttributeInt(null, ATTR_INSTALL_REASON,
+ PackageManager.INSTALL_REASON_UNKNOWN);
+ final int uninstallReason = parser.getAttributeInt(null,
+ ATTR_UNINSTALL_REASON,
+ PackageManager.UNINSTALL_REASON_UNKNOWN);
+ final String splashScreenTheme = parser.getAttributeValue(null,
+ ATTR_SPLASH_SCREEN_THEME);
+ final long firstInstallTime = parser.getAttributeLongHex(null,
+ ATTR_FIRST_INSTALL_TIME, 0);
+
+ ArraySet<String> enabledComponents = null;
+ ArraySet<String> disabledComponents = null;
+ PersistableBundle suspendedAppExtras = null;
+ PersistableBundle suspendedLauncherExtras = null;
+ SuspendDialogInfo oldSuspendDialogInfo = null;
+
+ int packageDepth = parser.getDepth();
+ ArrayMap<String, SuspendParams> suspendParamsMap = null;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > packageDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ switch (parser.getName()) {
+ case TAG_ENABLED_COMPONENTS:
+ enabledComponents = readComponentsLPr(parser);
+ break;
+ case TAG_DISABLED_COMPONENTS:
+ disabledComponents = readComponentsLPr(parser);
+ break;
+ case TAG_SUSPENDED_APP_EXTRAS:
+ suspendedAppExtras = PersistableBundle.restoreFromXml(parser);
+ break;
+ case TAG_SUSPENDED_LAUNCHER_EXTRAS:
+ suspendedLauncherExtras = PersistableBundle.restoreFromXml(
+ parser);
+ break;
+ case TAG_SUSPENDED_DIALOG_INFO:
+ oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
+ break;
+ case TAG_SUSPEND_PARAMS:
+ final String suspendingPackage = parser.getAttributeValue(null,
+ ATTR_SUSPENDING_PACKAGE);
+ if (suspendingPackage == null) {
+ Slog.wtf(TAG, "No suspendingPackage found inside tag "
+ + TAG_SUSPEND_PARAMS);
+ continue;
+ }
+ if (suspendParamsMap == null) {
+ suspendParamsMap = new ArrayMap<>();
+ }
+ suspendParamsMap.put(suspendingPackage,
+ SuspendParams.restoreFromXml(parser));
+ break;
+ default:
+ Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
+ + TAG_PACKAGE);
+ }
+ }
+ if (oldSuspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
+ oldSuspendDialogInfo = new SuspendDialogInfo.Builder()
+ .setMessage(dialogMessage)
+ .build();
+ }
+ if (suspended && suspendParamsMap == null) {
+ final SuspendParams suspendParams = new SuspendParams(
+ oldSuspendDialogInfo,
+ suspendedAppExtras,
+ suspendedLauncherExtras);
+ suspendParamsMap = new ArrayMap<>();
+ suspendParamsMap.put(oldSuspendingPackage, suspendParams);
+ }
+
+ if (blockUninstall) {
+ setBlockUninstallLPw(userId, name, true);
+ }
+ ps.setUserState(userId, ceDataInode, enabled, installed, stopped,
+ notLaunched,
+ hidden, distractionFlags, suspendParamsMap, instantApp,
+ virtualPreload,
+ enabledCaller, enabledComponents, disabledComponents, installReason,
+ uninstallReason, harmfulAppWarning, splashScreenTheme,
+ firstInstallTime != 0 ? firstInstallTime :
+ origFirstInstallTimes.getOrDefault(name, 0L));
+
+ mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
+ } else if (tagName.equals("preferred-activities")) {
+ readPreferredActivitiesLPw(parser, userId);
+ } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
+ readPersistentPreferredActivitiesLPw(parser, userId);
+ } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
+ readCrossProfileIntentFiltersLPw(parser, userId);
+ } else if (tagName.equals(TAG_DEFAULT_APPS)) {
+ readDefaultAppsLPw(parser, userId);
+ } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
+ readBlockUninstallPackagesLPw(parser, userId);
+ } else {
+ Slog.w(PackageManagerService.TAG,
+ "Unknown element under <stopped-packages>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
}
+ } catch (IOException | XmlPullParserException e) {
+ // Remove corrupted file and retry.
+ atomicFile.failRead(str, e);
+
+ readPackageRestrictionsLPr(userId, origFirstInstallTimes);
}
-
- str.close();
- } catch (XmlPullParserException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR,
- "Error reading stopped packages: " + e);
- Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
- e);
-
- } catch (java.io.IOException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
- Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
- e);
}
}
@@ -2170,219 +2146,176 @@
Log.i(TAG, "Writing package restrictions for user=" + userId);
}
- final File userPackagesStateFile;
- final File backupFile;
- final FileOutputStream fstr;
+ FileOutputStream str = null;
+ try (ResilientAtomicFile atomicFile = getUserPackagesStateFile(userId)) {
+ try {
+ synchronized (mPackageRestrictionsLock) {
+ if (!sync) {
+ int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) - 1;
+ if (pending < 0) {
+ Log.i(TAG, "Cancel writing package restrictions for user=" + userId);
+ return;
+ }
+ mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
+ }
- synchronized (mPackageRestrictionsLock) {
- if (!sync) {
- int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) - 1;
- if (pending < 0) {
- Log.i(TAG, "Cancel writing package restrictions for user=" + userId);
- return;
- }
- mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
- }
-
- // Keep the old stopped packages around until we know the new ones have
- // been successfully written.
- userPackagesStateFile = getUserPackagesStateFile(userId);
- backupFile = getUserPackagesStateBackupFile(userId);
- new File(userPackagesStateFile.getParent()).mkdirs();
- if (userPackagesStateFile.exists()) {
- // Presence of backup settings file indicates that we failed
- // to persist packages earlier. So preserve the older
- // backup for future reference since the current packages
- // might have been corrupted.
- if (!backupFile.exists()) {
- if (!userPackagesStateFile.renameTo(backupFile)) {
+ try {
+ str = atomicFile.startWrite();
+ } catch (java.io.IOException e) {
Slog.wtf(PackageManagerService.TAG,
- "Unable to backup user packages state file, "
- + "current changes will be lost at reboot");
+ "Unable to write package manager package restrictions, "
+ + " current changes will be lost at reboot", e);
return;
}
- } else {
- userPackagesStateFile.delete();
- Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
}
- }
- try {
- fstr = new FileOutputStream(userPackagesStateFile);
- // File is created, set permissions.
- FileUtils.setPermissions(userPackagesStateFile.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR
- | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
- -1, -1);
- } catch (java.io.IOException e) {
- Slog.wtf(PackageManagerService.TAG,
- "Unable to write package manager user packages state, "
- + " current changes will be lost at reboot", e);
- return;
- }
- }
+ synchronized (mLock) {
+ final TypedXmlSerializer serializer = Xml.resolveSerializer(str);
+ serializer.startDocument(null, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+ true);
- try {
- synchronized (mLock) {
- final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
- true);
+ serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
- serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
+ if (DEBUG_MU) {
+ Slogf.i(TAG, "Writing %s (%d packages)", atomicFile,
+ mPackages.values().size());
+ }
+ for (final PackageSetting pkg : mPackages.values()) {
+ final PackageUserStateInternal ustate = pkg.readUserState(userId);
+ if (DEBUG_MU) {
+ Log.v(TAG, " pkg=" + pkg.getPackageName()
+ + ", installed=" + ustate.isInstalled()
+ + ", state=" + ustate.getEnabledState());
+ }
+
+ serializer.startTag(null, TAG_PACKAGE);
+ serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
+ if (ustate.getCeDataInode() != 0) {
+ serializer.attributeLong(null, ATTR_CE_DATA_INODE,
+ ustate.getCeDataInode());
+ }
+ if (!ustate.isInstalled()) {
+ serializer.attributeBoolean(null, ATTR_INSTALLED, false);
+ }
+ if (ustate.isStopped()) {
+ serializer.attributeBoolean(null, ATTR_STOPPED, true);
+ }
+ if (ustate.isNotLaunched()) {
+ serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
+ }
+ if (ustate.isHidden()) {
+ serializer.attributeBoolean(null, ATTR_HIDDEN, true);
+ }
+ if (ustate.getDistractionFlags() != 0) {
+ serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
+ ustate.getDistractionFlags());
+ }
+ if (ustate.isSuspended()) {
+ serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
+ }
+ if (ustate.isInstantApp()) {
+ serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
+ }
+ if (ustate.isVirtualPreload()) {
+ serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
+ }
+ if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
+ serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
+ if (ustate.getLastDisableAppCaller() != null) {
+ serializer.attribute(null, ATTR_ENABLED_CALLER,
+ ustate.getLastDisableAppCaller());
+ }
+ }
+ if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
+ serializer.attributeInt(null, ATTR_INSTALL_REASON,
+ ustate.getInstallReason());
+ }
+ serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
+ ustate.getFirstInstallTimeMillis());
+ if (ustate.getUninstallReason()
+ != PackageManager.UNINSTALL_REASON_UNKNOWN) {
+ serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
+ ustate.getUninstallReason());
+ }
+ if (ustate.getHarmfulAppWarning() != null) {
+ serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
+ ustate.getHarmfulAppWarning());
+ }
+ if (ustate.getSplashScreenTheme() != null) {
+ serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
+ ustate.getSplashScreenTheme());
+ }
+ if (ustate.isSuspended()) {
+ for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
+ final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
+ serializer.startTag(null, TAG_SUSPEND_PARAMS);
+ serializer.attribute(null, ATTR_SUSPENDING_PACKAGE,
+ suspendingPackage);
+ final SuspendParams params =
+ ustate.getSuspendParams().valueAt(i);
+ if (params != null) {
+ params.saveToXml(serializer);
+ }
+ serializer.endTag(null, TAG_SUSPEND_PARAMS);
+ }
+ }
+ final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
+ if (enabledComponents != null && enabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_ENABLED_COMPONENTS);
+ for (int i = 0; i < enabledComponents.size(); i++) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME,
+ enabledComponents.valueAt(i));
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_ENABLED_COMPONENTS);
+ }
+ final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
+ if (disabledComponents != null && disabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_DISABLED_COMPONENTS);
+ for (int i = 0; i < disabledComponents.size(); i++) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME,
+ disabledComponents.valueAt(i));
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_DISABLED_COMPONENTS);
+ }
+
+ serializer.endTag(null, TAG_PACKAGE);
+ }
+
+ writePreferredActivitiesLPr(serializer, userId, true);
+ writePersistentPreferredActivitiesLPr(serializer, userId);
+ writeCrossProfileIntentFiltersLPr(serializer, userId);
+ writeDefaultAppsLPr(serializer, userId);
+ writeBlockUninstallPackagesLPr(serializer, userId);
+
+ serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
+
+ serializer.endDocument();
+ }
+
+ atomicFile.finishWrite(str);
if (DEBUG_MU) {
- Slogf.i(TAG, "Writing %s (%d packages)", userPackagesStateFile,
- mPackages.values().size());
- }
- for (final PackageSetting pkg : mPackages.values()) {
- final PackageUserStateInternal ustate = pkg.readUserState(userId);
- if (DEBUG_MU) {
- Log.v(TAG, " pkg=" + pkg.getPackageName()
- + ", installed=" + ustate.isInstalled()
- + ", state=" + ustate.getEnabledState());
- }
-
- serializer.startTag(null, TAG_PACKAGE);
- serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
- if (ustate.getCeDataInode() != 0) {
- serializer.attributeLong(null, ATTR_CE_DATA_INODE, ustate.getCeDataInode());
- }
- if (!ustate.isInstalled()) {
- serializer.attributeBoolean(null, ATTR_INSTALLED, false);
- }
- if (ustate.isStopped()) {
- serializer.attributeBoolean(null, ATTR_STOPPED, true);
- }
- if (ustate.isNotLaunched()) {
- serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
- }
- if (ustate.isHidden()) {
- serializer.attributeBoolean(null, ATTR_HIDDEN, true);
- }
- if (ustate.getDistractionFlags() != 0) {
- serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
- ustate.getDistractionFlags());
- }
- if (ustate.isSuspended()) {
- serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
- }
- if (ustate.isInstantApp()) {
- serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
- }
- if (ustate.isVirtualPreload()) {
- serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
- }
- if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
- serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
- if (ustate.getLastDisableAppCaller() != null) {
- serializer.attribute(null, ATTR_ENABLED_CALLER,
- ustate.getLastDisableAppCaller());
- }
- }
- if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
- serializer.attributeInt(null, ATTR_INSTALL_REASON,
- ustate.getInstallReason());
- }
- serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
- ustate.getFirstInstallTimeMillis());
- if (ustate.getUninstallReason() != PackageManager.UNINSTALL_REASON_UNKNOWN) {
- serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
- ustate.getUninstallReason());
- }
- if (ustate.getHarmfulAppWarning() != null) {
- serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
- ustate.getHarmfulAppWarning());
- }
- if (ustate.getSplashScreenTheme() != null) {
- serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
- ustate.getSplashScreenTheme());
- }
- if (ustate.isSuspended()) {
- for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
- final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
- serializer.startTag(null, TAG_SUSPEND_PARAMS);
- serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, suspendingPackage);
- final SuspendParams params =
- ustate.getSuspendParams().valueAt(i);
- if (params != null) {
- params.saveToXml(serializer);
- }
- serializer.endTag(null, TAG_SUSPEND_PARAMS);
- }
- }
- final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
- if (enabledComponents != null && enabledComponents.size() > 0) {
- serializer.startTag(null, TAG_ENABLED_COMPONENTS);
- for (int i = 0; i < enabledComponents.size(); i++) {
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME,
- enabledComponents.valueAt(i));
- serializer.endTag(null, TAG_ITEM);
- }
- serializer.endTag(null, TAG_ENABLED_COMPONENTS);
- }
- final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
- if (disabledComponents != null && disabledComponents.size() > 0) {
- serializer.startTag(null, TAG_DISABLED_COMPONENTS);
- for (int i = 0; i < disabledComponents.size(); i++) {
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME,
- disabledComponents.valueAt(i));
- serializer.endTag(null, TAG_ITEM);
- }
- serializer.endTag(null, TAG_DISABLED_COMPONENTS);
- }
-
- serializer.endTag(null, TAG_PACKAGE);
+ Log.i(TAG, "New package restrictions successfully written for user=" + userId
+ + ": " + atomicFile);
}
- writePreferredActivitiesLPr(serializer, userId, true);
- writePersistentPreferredActivitiesLPr(serializer, userId);
- writeCrossProfileIntentFiltersLPr(serializer, userId);
- writeDefaultAppsLPr(serializer, userId);
- writeBlockUninstallPackagesLPr(serializer, userId);
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
- serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
-
- serializer.endDocument();
- }
-
- fstr.flush();
- FileUtils.sync(fstr);
- IoUtils.closeQuietly(fstr);
-
- synchronized (mPackageRestrictionsLock) {
- // File is created, set permissions.
- FileUtils.setPermissions(userPackagesStateFile.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR
- | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
- -1, -1);
- // New settings successfully written, old ones are no longer needed.
- backupFile.delete();
- }
-
- if (DEBUG_MU) {
- Log.i(TAG, "New settings successfully written for user=" + userId + ": "
- + userPackagesStateFile);
- }
-
- com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
- "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
-
- // Done, all is good!
- return;
- } catch (java.io.IOException e) {
- Slog.wtf(PackageManagerService.TAG,
- "Unable to write package manager user packages state, "
- + " current changes will be lost at reboot", e);
- }
-
- // Clean up partially written files
- if (userPackagesStateFile.exists()) {
- if (!userPackagesStateFile.delete()) {
- Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
- + mStoppedPackagesFilename);
+ // Done, all is good!
+ return;
+ } catch (java.io.IOException e) {
+ Slog.wtf(PackageManagerService.TAG,
+ "Unable to write package manager package restrictions, "
+ + " current changes will be lost at reboot", e);
+ if (str != null) {
+ atomicFile.failWrite(str);
+ }
}
}
}
@@ -2594,153 +2527,108 @@
// right time.
invalidatePackageCache();
- // Keep the old settings around until we know the new ones have
- // been successfully written.
- if (mSettingsFilename.exists()) {
- // Presence of backup settings file indicates that we failed
- // to persist settings earlier. So preserve the older
- // backup for future reference since the current settings
- // might have been corrupted.
- if (!mPreviousSettingsFilename.exists()) {
- if (!mSettingsFilename.renameTo(mPreviousSettingsFilename)) {
- Slog.wtf(PackageManagerService.TAG,
- "Unable to store older package manager settings, "
- + " current changes will be lost at reboot");
- return;
- }
- } else {
- mSettingsFilename.delete();
- Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
- }
- }
-
mPastSignatures.clear();
- try {
- final FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
- final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
- serializer.startTag(null, "packages");
-
- for (int i = 0; i < mVersion.size(); i++) {
- final String volumeUuid = mVersion.keyAt(i);
- final VersionInfo ver = mVersion.valueAt(i);
-
- serializer.startTag(null, TAG_VERSION);
- XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
- serializer.attributeInt(null, ATTR_SDK_VERSION, ver.sdkVersion);
- serializer.attributeInt(null, ATTR_DATABASE_VERSION, ver.databaseVersion);
- XmlUtils.writeStringAttribute(serializer, ATTR_BUILD_FINGERPRINT,
- ver.buildFingerprint);
- XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
- serializer.endTag(null, TAG_VERSION);
- }
-
- if (mVerifierDeviceIdentity != null) {
- serializer.startTag(null, "verifier");
- serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
- serializer.endTag(null, "verifier");
- }
-
- serializer.startTag(null, "permission-trees");
- mPermissions.writePermissionTrees(serializer);
- serializer.endTag(null, "permission-trees");
-
- serializer.startTag(null, "permissions");
- mPermissions.writePermissions(serializer);
- serializer.endTag(null, "permissions");
-
- for (final PackageSetting pkg : mPackages.values()) {
- if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
- // Don't persist APEX which doesn't have a valid app id and will fail to load
- continue;
- }
- writePackageLPr(serializer, pkg);
- }
-
- for (final PackageSetting pkg : mDisabledSysPackages.values()) {
- if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
- // Don't persist APEX which doesn't have a valid app id and will fail to load
- continue;
- }
- writeDisabledSysPackageLPr(serializer, pkg);
- }
-
- for (final SharedUserSetting usr : mSharedUsers.values()) {
- serializer.startTag(null, "shared-user");
- serializer.attribute(null, ATTR_NAME, usr.name);
- serializer.attributeInt(null, "userId", usr.mAppId);
- usr.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
- serializer.endTag(null, "shared-user");
- }
-
- if (mRenamedPackages.size() > 0) {
- for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
- serializer.startTag(null, "renamed-package");
- serializer.attribute(null, "new", e.getKey());
- serializer.attribute(null, "old", e.getValue());
- serializer.endTag(null, "renamed-package");
- }
- }
-
- mDomainVerificationManager.writeSettings(computer, serializer,
- false /* includeSignatures */, UserHandle.USER_ALL);
-
- mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
-
- serializer.endTag(null, "packages");
-
- serializer.endDocument();
-
- fstr.flush();
- FileUtils.sync(fstr);
- fstr.close();
-
- // New settings successfully written, old ones are no longer needed.
- mPreviousSettingsFilename.delete();
- mSettingsReserveCopyFilename.delete();
-
- FileUtils.setPermissions(mSettingsFilename.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
- -1, -1);
-
- try (FileInputStream in = new FileInputStream(mSettingsFilename);
- FileOutputStream out = new FileOutputStream(mSettingsReserveCopyFilename)) {
- FileUtils.copy(in, out);
- out.flush();
- FileUtils.sync(out);
- } catch (IOException e) {
- Slog.e(TAG,
- "Failed to write reserve copy of settings: " + mSettingsReserveCopyFilename,
- e);
- }
-
+ try (ResilientAtomicFile atomicFile = getSettingsFile()) {
+ FileOutputStream str = null;
try {
- FileIntegrity.setUpFsVerity(mSettingsFilename);
- FileIntegrity.setUpFsVerity(mSettingsReserveCopyFilename);
- } catch (IOException e) {
- Slog.e(TAG, "Failed to verity-protect settings", e);
- }
+ str = atomicFile.startWrite();
- writeKernelMappingLPr();
- writePackageListLPr();
- writeAllUsersPackageRestrictionsLPr(sync);
- writeAllRuntimePermissionsLPr();
- com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
- "package", SystemClock.uptimeMillis() - startTime);
- return;
+ final TypedXmlSerializer serializer = Xml.resolveSerializer(str);
+ serializer.startDocument(null, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+ true);
- } catch(java.io.IOException e) {
- Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
- + "current changes will be lost at reboot", e);
- }
- // Clean up partially written files
- if (mSettingsFilename.exists()) {
- if (!mSettingsFilename.delete()) {
- Slog.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
- + mSettingsFilename);
+ serializer.startTag(null, "packages");
+
+ for (int i = 0; i < mVersion.size(); i++) {
+ final String volumeUuid = mVersion.keyAt(i);
+ final VersionInfo ver = mVersion.valueAt(i);
+
+ serializer.startTag(null, TAG_VERSION);
+ XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
+ serializer.attributeInt(null, ATTR_SDK_VERSION, ver.sdkVersion);
+ serializer.attributeInt(null, ATTR_DATABASE_VERSION, ver.databaseVersion);
+ XmlUtils.writeStringAttribute(serializer, ATTR_BUILD_FINGERPRINT,
+ ver.buildFingerprint);
+ XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
+ serializer.endTag(null, TAG_VERSION);
+ }
+
+ if (mVerifierDeviceIdentity != null) {
+ serializer.startTag(null, "verifier");
+ serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
+ serializer.endTag(null, "verifier");
+ }
+
+ serializer.startTag(null, "permission-trees");
+ mPermissions.writePermissionTrees(serializer);
+ serializer.endTag(null, "permission-trees");
+
+ serializer.startTag(null, "permissions");
+ mPermissions.writePermissions(serializer);
+ serializer.endTag(null, "permissions");
+
+ for (final PackageSetting pkg : mPackages.values()) {
+ if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
+ // Don't persist APEX which doesn't have a valid app id and will fail to
+ // load
+ continue;
+ }
+ writePackageLPr(serializer, pkg);
+ }
+
+ for (final PackageSetting pkg : mDisabledSysPackages.values()) {
+ if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
+ // Don't persist APEX which doesn't have a valid app id and will fail to
+ // load
+ continue;
+ }
+ writeDisabledSysPackageLPr(serializer, pkg);
+ }
+
+ for (final SharedUserSetting usr : mSharedUsers.values()) {
+ serializer.startTag(null, "shared-user");
+ serializer.attribute(null, ATTR_NAME, usr.name);
+ serializer.attributeInt(null, "userId", usr.mAppId);
+ usr.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
+ serializer.endTag(null, "shared-user");
+ }
+
+ if (mRenamedPackages.size() > 0) {
+ for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
+ serializer.startTag(null, "renamed-package");
+ serializer.attribute(null, "new", e.getKey());
+ serializer.attribute(null, "old", e.getValue());
+ serializer.endTag(null, "renamed-package");
+ }
+ }
+
+ mDomainVerificationManager.writeSettings(computer, serializer,
+ false /* includeSignatures */, UserHandle.USER_ALL);
+
+ mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
+
+ serializer.endTag(null, "packages");
+
+ serializer.endDocument();
+
+ atomicFile.finishWrite(str);
+
+ writeKernelMappingLPr();
+ writePackageListLPr();
+ writeAllUsersPackageRestrictionsLPr(sync);
+ writeAllRuntimePermissionsLPr();
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "package", SystemClock.uptimeMillis() - startTime);
+ return;
+
+ } catch (java.io.IOException e) {
+ Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
+ + "current changes will be lost at reboot", e);
+ if (str != null) {
+ atomicFile.failWrite(str);
+ }
}
}
//Debug.stopMethodTracing();
@@ -3165,183 +3053,140 @@
mInstallerPackages.clear();
originalFirstInstallTimes.clear();
- File file = null;
- FileInputStream str = null;
+ try (ResilientAtomicFile atomicFile = getSettingsFile()) {
+ FileInputStream str = null;
+ try {
+ str = atomicFile.openRead();
+ if (str == null) {
+ // Not necessary, but will avoid wtf-s in the "finally" section.
+ findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent();
+ findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent();
+ return false;
+ }
+ final TypedXmlPullParser parser = Xml.resolvePullParser(str);
- try {
- // Check if the previous write was incomplete.
- if (mPreviousSettingsFilename.exists()) {
- try {
- file = mPreviousSettingsFilename;
- str = new FileInputStream(file);
- mReadMessages.append("Reading from backup settings file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "Need to read from backup settings file");
- if (mSettingsFilename.exists()) {
- // If both the previous and current settings files exist,
- // we ignore the current since it might have been corrupted.
- Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
- + mSettingsFilename);
- mSettingsFilename.delete();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // nothing
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ mReadMessages.append("No start tag found in settings file\n");
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "No start tag found in package manager settings");
+ Slog.wtf(PackageManagerService.TAG,
+ "No start tag found in package manager settings");
+ return false;
+ }
+
+ int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
}
- // Ignore reserve copy as well.
- mSettingsReserveCopyFilename.delete();
- } catch (java.io.IOException e) {
- // We'll try for the normal settings file.
- }
- }
- if (str == null) {
- if (mSettingsFilename.exists()) {
- // Using packages.xml.
- file = mSettingsFilename;
- str = new FileInputStream(file);
- } else if (mSettingsReserveCopyFilename.exists()) {
- // Using reserve copy.
- file = mSettingsReserveCopyFilename;
- str = new FileInputStream(file);
- mReadMessages.append("Reading from reserve copy settings file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "Need to read from reserve copy settings file");
- }
- }
- if (str == null) {
- // No available data sources.
- mReadMessages.append("No settings file found\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "No settings file; creating initial state");
- // Not necessary, but will avoid wtf-s in the "finally" section.
- findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent();
- findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent();
- return false;
- }
- final TypedXmlPullParser parser = Xml.resolvePullParser(str);
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- ;
- }
+ String tagName = parser.getName();
+ if (tagName.equals("package")) {
+ readPackageLPw(parser, users, originalFirstInstallTimes);
+ } else if (tagName.equals("permissions")) {
+ mPermissions.readPermissions(parser);
+ } else if (tagName.equals("permission-trees")) {
+ mPermissions.readPermissionTrees(parser);
+ } else if (tagName.equals("shared-user")) {
+ readSharedUserLPw(parser, users);
+ } else if (tagName.equals("preferred-packages")) {
+ // no longer used.
+ } else if (tagName.equals("preferred-activities")) {
+ // Upgrading from old single-user implementation;
+ // these are the preferred activities for user 0.
+ readPreferredActivitiesLPw(parser, 0);
+ } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
+ // TODO: check whether this is okay! as it is very
+ // similar to how preferred-activities are treated
+ readPersistentPreferredActivitiesLPw(parser, 0);
+ } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
+ // TODO: check whether this is okay! as it is very
+ // similar to how preferred-activities are treated
+ readCrossProfileIntentFiltersLPw(parser, 0);
+ } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
+ readDefaultAppsLPw(parser, 0);
+ } else if (tagName.equals("updated-package")) {
+ readDisabledSysPackageLPw(parser, users);
+ } else if (tagName.equals("renamed-package")) {
+ String nname = parser.getAttributeValue(null, "new");
+ String oname = parser.getAttributeValue(null, "old");
+ if (nname != null && oname != null) {
+ mRenamedPackages.put(nname, oname);
+ }
+ } else if (tagName.equals("last-platform-version")) {
+ // Upgrade from older XML schema
+ final VersionInfo internal = findOrCreateVersion(
+ StorageManager.UUID_PRIVATE_INTERNAL);
+ final VersionInfo external = findOrCreateVersion(
+ StorageManager.UUID_PRIMARY_PHYSICAL);
- if (type != XmlPullParser.START_TAG) {
- mReadMessages.append("No start tag found in settings file\n");
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "No start tag found in package manager settings");
- Slog.wtf(PackageManagerService.TAG,
- "No start tag found in package manager settings");
- return false;
- }
+ internal.sdkVersion = parser.getAttributeInt(null, "internal", 0);
+ external.sdkVersion = parser.getAttributeInt(null, "external", 0);
+ internal.buildFingerprint = external.buildFingerprint =
+ XmlUtils.readStringAttribute(parser, "buildFingerprint");
+ internal.fingerprint = external.fingerprint =
+ XmlUtils.readStringAttribute(parser, "fingerprint");
- int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
+ } else if (tagName.equals("database-version")) {
+ // Upgrade from older XML schema
+ final VersionInfo internal = findOrCreateVersion(
+ StorageManager.UUID_PRIVATE_INTERNAL);
+ final VersionInfo external = findOrCreateVersion(
+ StorageManager.UUID_PRIMARY_PHYSICAL);
- String tagName = parser.getName();
- if (tagName.equals("package")) {
- readPackageLPw(parser, users, originalFirstInstallTimes);
- } else if (tagName.equals("permissions")) {
- mPermissions.readPermissions(parser);
- } else if (tagName.equals("permission-trees")) {
- mPermissions.readPermissionTrees(parser);
- } else if (tagName.equals("shared-user")) {
- readSharedUserLPw(parser, users);
- } else if (tagName.equals("preferred-packages")) {
- // no longer used.
- } else if (tagName.equals("preferred-activities")) {
- // Upgrading from old single-user implementation;
- // these are the preferred activities for user 0.
- readPreferredActivitiesLPw(parser, 0);
- } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
- // TODO: check whether this is okay! as it is very
- // similar to how preferred-activities are treated
- readPersistentPreferredActivitiesLPw(parser, 0);
- } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
- // TODO: check whether this is okay! as it is very
- // similar to how preferred-activities are treated
- readCrossProfileIntentFiltersLPw(parser, 0);
- } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
- readDefaultAppsLPw(parser, 0);
- } else if (tagName.equals("updated-package")) {
- readDisabledSysPackageLPw(parser, users);
- } else if (tagName.equals("renamed-package")) {
- String nname = parser.getAttributeValue(null, "new");
- String oname = parser.getAttributeValue(null, "old");
- if (nname != null && oname != null) {
- mRenamedPackages.put(nname, oname);
+ internal.databaseVersion = parser.getAttributeInt(null, "internal", 0);
+ external.databaseVersion = parser.getAttributeInt(null, "external", 0);
+
+ } else if (tagName.equals("verifier")) {
+ final String deviceIdentity = parser.getAttributeValue(null, "device");
+ try {
+ mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
+ } catch (IllegalArgumentException e) {
+ Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
+ + e.getMessage());
+ }
+ } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
+ // No longer used.
+ } else if (tagName.equals("keyset-settings")) {
+ mKeySetManagerService.readKeySetsLPw(parser,
+ mKeySetRefs.untrackedStorage());
+ } else if (TAG_VERSION.equals(tagName)) {
+ final String volumeUuid = XmlUtils.readStringAttribute(parser,
+ ATTR_VOLUME_UUID);
+ final VersionInfo ver = findOrCreateVersion(volumeUuid);
+ ver.sdkVersion = parser.getAttributeInt(null, ATTR_SDK_VERSION);
+ ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION);
+ ver.buildFingerprint = XmlUtils.readStringAttribute(parser,
+ ATTR_BUILD_FINGERPRINT);
+ ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
+ } else if (tagName.equals(
+ DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) {
+ mDomainVerificationManager.readSettings(computer, parser);
+ } else if (tagName.equals(
+ DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) {
+ mDomainVerificationManager.readLegacySettings(parser);
+ } else {
+ Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
}
- } else if (tagName.equals("last-platform-version")) {
- // Upgrade from older XML schema
- final VersionInfo internal = findOrCreateVersion(
- StorageManager.UUID_PRIVATE_INTERNAL);
- final VersionInfo external = findOrCreateVersion(
- StorageManager.UUID_PRIMARY_PHYSICAL);
-
- internal.sdkVersion = parser.getAttributeInt(null, "internal", 0);
- external.sdkVersion = parser.getAttributeInt(null, "external", 0);
- internal.buildFingerprint = external.buildFingerprint =
- XmlUtils.readStringAttribute(parser, "buildFingerprint");
- internal.fingerprint = external.fingerprint =
- XmlUtils.readStringAttribute(parser, "fingerprint");
-
- } else if (tagName.equals("database-version")) {
- // Upgrade from older XML schema
- final VersionInfo internal = findOrCreateVersion(
- StorageManager.UUID_PRIVATE_INTERNAL);
- final VersionInfo external = findOrCreateVersion(
- StorageManager.UUID_PRIMARY_PHYSICAL);
-
- internal.databaseVersion = parser.getAttributeInt(null, "internal", 0);
- external.databaseVersion = parser.getAttributeInt(null, "external", 0);
-
- } else if (tagName.equals("verifier")) {
- final String deviceIdentity = parser.getAttributeValue(null, "device");
- try {
- mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
- } catch (IllegalArgumentException e) {
- Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
- + e.getMessage());
- }
- } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
- // No longer used.
- } else if (tagName.equals("keyset-settings")) {
- mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs.untrackedStorage());
- } else if (TAG_VERSION.equals(tagName)) {
- final String volumeUuid = XmlUtils.readStringAttribute(parser,
- ATTR_VOLUME_UUID);
- final VersionInfo ver = findOrCreateVersion(volumeUuid);
- ver.sdkVersion = parser.getAttributeInt(null, ATTR_SDK_VERSION);
- ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION);
- ver.buildFingerprint = XmlUtils.readStringAttribute(parser,
- ATTR_BUILD_FINGERPRINT);
- ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
- } else if (tagName.equals(DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) {
- mDomainVerificationManager.readSettings(computer, parser);
- } else if (tagName.equals(
- DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) {
- mDomainVerificationManager.readLegacySettings(parser);
- } else {
- Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
}
+
+ str.close();
+ } catch (IOException | XmlPullParserException e) {
+ // Remove corrupted file and retry.
+ atomicFile.failRead(str, e);
+
+ // Ignore the result to not mark this as a "first boot".
+ readSettingsLPw(computer, users, originalFirstInstallTimes);
}
-
- str.close();
- } catch (IOException | XmlPullParserException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
- Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
-
- // Remove corrupted file and retry.
- Slog.e(TAG,
- "Error reading package manager settings, removing " + file + " and retrying.",
- e);
- file.delete();
-
- // Ignore the result to not mark this as a "first boot".
- readSettingsLPw(computer, users, originalFirstInstallTimes);
}
return true;
@@ -4493,10 +4338,7 @@
mPreferredActivities.remove(userId);
synchronized (mPackageRestrictionsLock) {
- File file = getUserPackagesStateFile(userId);
- file.delete();
- file = getUserPackagesStateBackupFile(userId);
- file.delete();
+ getUserPackagesStateFile(userId).delete();
mPendingAsyncPackageRestrictionsWrites.delete(userId);
}
@@ -5039,19 +4881,20 @@
}
}
pw.print(prefix); pw.print(" timeStamp=");
- date.setTime(ps.getLastModifiedTime());
- pw.println(sdf.format(date));
+ date.setTime(ps.getLastModifiedTime());
+ pw.println(sdf.format(date));
pw.print(prefix); pw.print(" lastUpdateTime=");
- date.setTime(ps.getLastUpdateTime());
- pw.println(sdf.format(date));
- if (ps.getInstallSource().mInstallerPackageName != null) {
- pw.print(prefix); pw.print(" installerPackageName=");
- pw.println(ps.getInstallSource().mInstallerPackageName);
- }
- if (ps.getInstallSource().mInstallerPackageUid != INVALID_UID) {
- pw.print(prefix); pw.print(" installerPackageUid=");
- pw.println(ps.getInstallSource().mInstallerPackageUid);
- }
+ date.setTime(ps.getLastUpdateTime());
+ pw.println(sdf.format(date));
+ pw.print(prefix); pw.print(" installerPackageName=");
+ pw.println(ps.getInstallSource().mInstallerPackageName);
+ pw.print(prefix); pw.print(" installerPackageUid=");
+ pw.println(ps.getInstallSource().mInstallerPackageUid);
+ pw.print(prefix); pw.print(" initiatingPackageName=");
+ pw.println(ps.getInstallSource().mInitiatingPackageName);
+ pw.print(prefix); pw.print(" originatingPackageName=");
+ pw.println(ps.getInstallSource().mOriginatingPackageName);
+
if (ps.getInstallSource().mUpdateOwnerPackageName != null) {
pw.print(prefix); pw.print(" updateOwnerPackageName=");
pw.println(ps.getInstallSource().mUpdateOwnerPackageName);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 6d5e2b0..28cb7f0 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -430,6 +430,7 @@
@NonNull List<ShortcutInfo> changedShortcuts) {
Preconditions.checkArgument(newShortcut.isEnabled(),
"pushDynamicShortcuts() cannot publish disabled shortcuts");
+ ensureShortcutCountBeforePush();
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -437,7 +438,7 @@
final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
boolean deleted = false;
- if (oldShortcut == null) {
+ if (oldShortcut == null || !oldShortcut.isDynamic()) {
final ShortcutService service = mShortcutUser.mService;
final int maxShortcuts = service.getMaxActivityShortcuts();
@@ -446,18 +447,12 @@
final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
- Slog.e(TAG, "Error pushing shortcut. There are already "
- + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
- + " shortcuts limit when pushing the new shortcut " + newShortcut
- + ". Id of shortcuts currently available in system memory are "
- + activityShortcuts.stream().map(ShortcutInfo::getId)
- .collect(Collectors.joining(",", "[", "]")));
- // TODO: This should not have happened. If it does, identify the root cause where
- // possible, otherwise bail-out early to prevent memory issue.
+ // Root cause was discovered in b/233155034, so this should not be happening.
+ service.wtf("Error pushing shortcut. There are already "
+ + activityShortcuts.size() + " shortcuts.");
}
if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
// Max has reached. Delete the shortcut with lowest rank.
-
// Sort by isManifestShortcut() and getRank().
Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
@@ -473,7 +468,8 @@
deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
/*ignorePersistedShortcuts=*/ true) != null;
}
- } else {
+ }
+ if (oldShortcut != null) {
// It's an update case.
// Make sure the target is updatable. (i.e. should be mutable.)
oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@
return deleted;
}
+ private void ensureShortcutCountBeforePush() {
+ final ShortcutService service = mShortcutUser.mService;
+ // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
+ final int maxShortcutPerApp = service.getMaxAppShortcuts();
+ synchronized (mLock) {
+ final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
+ !si.isPinned()).collect(Collectors.toList());
+ if (appShortcuts.size() >= maxShortcutPerApp) {
+ // Max has reached. Removes shortcuts until they fall within the hard cap.
+ // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
+ Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
+
+ while (appShortcuts.size() >= maxShortcutPerApp) {
+ final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
+ if (shortcut.isDeclaredInManifest()) {
+ // All shortcuts are manifest shortcuts and cannot be removed.
+ throw new IllegalArgumentException(getPackageName() + " has published "
+ + appShortcuts.size() + " manifest shortcuts across different"
+ + " activities.");
+ }
+ forceDeleteShortcutInner(shortcut.getId());
+ }
+ }
+ }
+ }
+
/**
* Remove all shortcuts that aren't pinned, cached nor dynamic.
*
@@ -1371,6 +1393,61 @@
};
/**
+ * To sort by isManifestShortcut(), isDynamic(), getRank() and
+ * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
+ * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
+ *
+ * This is used to decide which shortcuts to remove when the total number of shortcuts retained
+ * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
+ *
+ * (Note the number of manifest shortcuts is always <= the max number, because if there are
+ * more, ShortcutParser would ignore the rest.)
+ */
+ final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
+ ShortcutInfo b) -> {
+ if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+ return -1;
+ }
+ if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+ return 1;
+ }
+ if (a.isDynamic() && b.isDynamic()) {
+ return Integer.compare(a.getRank(), b.getRank());
+ }
+ if (a.isDynamic()) {
+ return -1;
+ }
+ if (b.isDynamic()) {
+ return 1;
+ }
+ if (a.isCached() && b.isCached()) {
+ // if both shortcuts are cached, prioritize shortcuts cached by people tile,
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return 1;
+ }
+ // followed by bubbles.
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return 1;
+ }
+ }
+ if (a.isCached()) {
+ return -1;
+ }
+ if (b.isCached()) {
+ return 1;
+ }
+ return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
+ };
+
+ /**
* Build a list of shortcuts for each target activity and return as a map. The result won't
* contain "floating" shortcuts because they don't belong on any activities.
*/
@@ -1971,6 +2048,9 @@
shortcutUser.getUserId(), fromBackup);
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
+ } catch (IOException e) {
+ // Don't ignore IO exceptions.
+ throw e;
} catch (Exception e) {
// b/246540168 malformed shortcuts should be ignored
Slog.e(TAG, "Failed parsing shortcut.", e);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index e20330d..8b118da 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -27,6 +27,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.security.FileIntegrity;
import org.json.JSONException;
import org.json.JSONObject;
@@ -180,6 +181,12 @@
os.flush();
file.finishWrite(os);
+
+ try {
+ FileIntegrity.setUpFsVerity(path);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to verity-protect " + path, e);
+ }
} catch (XmlPullParserException | IOException e) {
Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
file.failWrite(os);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index b7c3b97..20cb485 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -119,7 +119,6 @@
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.security.FileIntegrity;
import com.android.server.uri.UriGrantsManagerInternal;
import org.json.JSONArray;
@@ -180,6 +179,9 @@
static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
@VisibleForTesting
+ static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;
+
+ @VisibleForTesting
static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
@VisibleForTesting
@@ -260,6 +262,11 @@
String KEY_MAX_SHORTCUTS = "max_shortcuts";
/**
+ * Key name for the max shortcuts can be retained in system ram per app. (int)
+ */
+ String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";
+
+ /**
* Key name for icon compression quality, 0-100.
*/
String KEY_ICON_QUALITY = "icon_quality";
@@ -332,11 +339,16 @@
new SparseArray<>();
/**
- * Max number of dynamic + manifest shortcuts that each application can have at a time.
+ * Max number of dynamic + manifest shortcuts that each activity can have at a time.
*/
private int mMaxShortcuts;
/**
+ * Max number of shortcuts that can exists in system ram for each application.
+ */
+ private int mMaxShortcutsPerApp;
+
+ /**
* Max number of updating API calls that each application can make during the interval.
*/
int mMaxUpdatesPerInterval;
@@ -810,6 +822,9 @@
mMaxShortcuts = Math.max(0, (int) parser.getLong(
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
+ mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
+ ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));
+
final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
? (int) parser.getLong(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1054,57 +1069,38 @@
}
@VisibleForTesting
- final File getUserFile(@UserIdInt int userId) {
- return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
- }
-
- @VisibleForTesting
- final File getReserveCopyUserFile(@UserIdInt int userId) {
- return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES_RESERVE_COPY);
+ final ResilientAtomicFile getUserFile(@UserIdInt int userId) {
+ File mainFile = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
+ File temporaryBackup = new File(injectUserDataPath(userId),
+ FILENAME_USER_PACKAGES + ".backup");
+ File reserveCopy = new File(injectUserDataPath(userId),
+ FILENAME_USER_PACKAGES_RESERVE_COPY);
+ int fileMode = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH;
+ return new ResilientAtomicFile(mainFile, temporaryBackup, reserveCopy, fileMode,
+ "user shortcut", null);
}
@GuardedBy("mLock")
private void saveUserLocked(@UserIdInt int userId) {
- final File path = getUserFile(userId);
- if (DEBUG || DEBUG_REBOOT) {
- Slog.d(TAG, "Saving to " + path);
- }
+ try (ResilientAtomicFile file = getUserFile(userId)) {
+ FileOutputStream os = null;
+ try {
+ if (DEBUG || DEBUG_REBOOT) {
+ Slog.d(TAG, "Saving to " + file);
+ }
- final File reservePath = getReserveCopyUserFile(userId);
- reservePath.delete();
+ os = file.startWrite();
- path.getParentFile().mkdirs();
- final AtomicFile file = new AtomicFile(path);
- FileOutputStream os = null;
- try {
- os = file.startWrite();
+ saveUserInternalLocked(userId, os, /* forBackup= */ false);
- saveUserInternalLocked(userId, os, /* forBackup= */ false);
+ file.finishWrite(os);
- file.finishWrite(os);
-
- // Remove all dangling bitmap files.
- cleanupDanglingBitmapDirectoriesLocked(userId);
- } catch (XmlPullParserException | IOException e) {
- Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
- file.failWrite(os);
- }
-
- // Store the reserve copy of the file.
- try (FileInputStream in = new FileInputStream(path);
- FileOutputStream out = new FileOutputStream(reservePath)) {
- FileUtils.copy(in, out);
- FileUtils.sync(out);
- } catch (IOException e) {
- Slog.e(TAG, "Failed to write reserve copy: " + path, e);
- }
-
- // Protect both primary and reserve copy with fs-verity.
- try {
- FileIntegrity.setUpFsVerity(path);
- FileIntegrity.setUpFsVerity(reservePath);
- } catch (IOException e) {
- Slog.e(TAG, "Failed to verity-protect", e);
+ // Remove all dangling bitmap files.
+ cleanupDanglingBitmapDirectoriesLocked(userId);
+ } catch (XmlPullParserException | IOException e) {
+ Slog.e(TAG, "Failed to write to file " + file, e);
+ file.failWrite(os);
+ }
}
getUserShortcutsLocked(userId).logSharingShortcutStats(mMetricsLogger);
@@ -1141,29 +1137,26 @@
@Nullable
private ShortcutUser loadUserLocked(@UserIdInt int userId) {
- final File path = getUserFile(userId);
- if (DEBUG || DEBUG_REBOOT) {
- Slog.d(TAG, "Loading from " + path);
- }
-
- try (FileInputStream in = new AtomicFile(path).openRead()) {
- return loadUserInternal(userId, in, /* forBackup= */ false);
- } catch (FileNotFoundException e) {
- if (DEBUG || DEBUG_REBOOT) {
- Slog.d(TAG, "Not found " + path);
- }
- } catch (Exception e) {
- final File reservePath = getReserveCopyUserFile(userId);
- Slog.e(TAG, "Reading from reserve copy: " + reservePath, e);
- try (FileInputStream in = new AtomicFile(reservePath).openRead()) {
+ try (ResilientAtomicFile file = getUserFile(userId)) {
+ FileInputStream in = null;
+ try {
+ if (DEBUG || DEBUG_REBOOT) {
+ Slog.d(TAG, "Loading from " + file);
+ }
+ in = file.openRead();
+ if (in == null) {
+ if (DEBUG || DEBUG_REBOOT) {
+ Slog.d(TAG, "Not found " + file);
+ }
+ return null;
+ }
return loadUserInternal(userId, in, /* forBackup= */ false);
- } catch (Exception exceptionReadingReserveFile) {
- Slog.e(TAG, "Failed to read reserve copy: " + reservePath,
- exceptionReadingReserveFile);
+ } catch (Exception e) {
+ // Remove corrupted file and retry.
+ file.failRead(in, e);
+ return loadUserLocked(userId);
}
- Slog.e(TAG, "Failed to read file " + path, e);
}
- return null;
}
private ShortcutUser loadUserInternal(@UserIdInt int userId, InputStream is,
@@ -1786,6 +1779,13 @@
}
/**
+ * Return the max number of shortcuts can be retaiend in system ram for each application.
+ */
+ int getMaxAppShortcuts() {
+ return mMaxShortcutsPerApp;
+ }
+
+ /**
* - Sends a notification to LauncherApps
* - Write to file
*/
@@ -4350,14 +4350,8 @@
@NonNull ComponentName activity, @UserIdInt int userId) {
final long start = getStatStartTime();
try {
- final ActivityInfo ai;
- try {
- ai = mContext.getPackageManager().getActivityInfoAsUser(activity,
- PackageManager.ComponentInfoFlags.of(PACKAGE_MATCH_FLAGS), userId);
- } catch (NameNotFoundException e) {
- return false;
- }
- return ai.enabled && ai.exported;
+ return queryActivities(new Intent(), activity.getPackageName(), activity, userId)
+ .size() > 0;
} finally {
logDurationStat(Stats.IS_ACTIVITY_ENABLED, start);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 9ef1bba..b4d467f 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -64,12 +64,11 @@
})
public @interface UserAssignmentResult {}
- // TODO(b/248408342): Move keep annotation to the method referencing these fields reflectively.
- @Keep public static final int USER_START_MODE_FOREGROUND = 1;
- @Keep public static final int USER_START_MODE_BACKGROUND = 2;
- @Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
-
private static final String PREFIX_USER_START_MODE = "USER_START_MODE_";
+
+ /**
+ * Type used to indicate how a user started.
+ */
@IntDef(flag = false, prefix = {PREFIX_USER_START_MODE}, value = {
USER_START_MODE_FOREGROUND,
USER_START_MODE_BACKGROUND,
@@ -77,6 +76,32 @@
})
public @interface UserStartMode {}
+ // TODO(b/248408342): Move keep annotations below to the method referencing these fields
+ // reflectively.
+
+ /** (Full) user started on foreground (a.k.a. "current user"). */
+ @Keep public static final int USER_START_MODE_FOREGROUND = 1;
+
+ /**
+ * User (full or profile) started on background and is
+ * {@link UserManager#isUserVisible() invisible}.
+ *
+ * <p>This is the "traditional" way of starting a background user, and can be used to start
+ * profiles as well, although starting an invisible profile is not common from the System UI
+ * (it could be done through APIs or adb, though).
+ */
+ @Keep public static final int USER_START_MODE_BACKGROUND = 2;
+
+ /**
+ * User (full or profile) started on background and is
+ * {@link UserManager#isUserVisible() visible}.
+ *
+ * <p>This is the "traditional" way of starting a profile (i.e., when the profile of the current
+ * user is the current foreground user), but it can also be used to start a full user associated
+ * with a display (which is the case on automotives with passenger displays).
+ */
+ @Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
+
public interface UserRestrictionsListener {
/**
* Called when a user restriction changes.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a54f06f..1a486dc 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -114,6 +114,7 @@
import android.util.TypedValue;
import android.util.Xml;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
@@ -2048,6 +2049,27 @@
+ "permission to: check " + name);
}
+ /**
+ * Enforces that the calling user is in the same profile group as {@code userId} or that only
+ * the system UID or root's UID or apps that have the
+ * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
+ * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} or
+ * {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}
+ * can make certain calls to the UserManager.
+ *
+ * @param userId the user's id
+ * @param name used as message if SecurityException is thrown
+ * @throws SecurityException if the caller lacks the required permissions.
+ */
+ private void checkQueryOrCreateUsersPermissionIfCallerInOtherProfileGroup(
+ @UserIdInt int userId, String name) {
+ final int callingUserId = UserHandle.getCallingUserId();
+ if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId)) {
+ return;
+ }
+ checkQueryOrCreateUsersPermission(name);
+ }
+
@Override
public boolean isDemoUser(@UserIdInt int userId) {
final int callingUserId = UserHandle.getCallingUserId();
@@ -2062,6 +2084,15 @@
}
@Override
+ public boolean isAdminUser(@UserIdInt int userId) {
+ checkQueryOrCreateUsersPermissionIfCallerInOtherProfileGroup(userId, "isAdminUser");
+ synchronized (mUsersLock) {
+ final UserInfo userInfo = getUserInfoLU(userId);
+ return userInfo != null && userInfo.isAdmin();
+ }
+ }
+
+ @Override
public boolean isPreCreated(@UserIdInt int userId) {
checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isPreCreated");
synchronized (mUsersLock) {
@@ -3621,6 +3652,13 @@
} finally {
IoUtils.closeQuietly(fis);
}
+
+ synchronized (mUsersLock) {
+ if (mUsers.size() == 0) {
+ Slog.e(LOG_TAG, "mUsers is empty, fallback to single user");
+ fallbackToSingleUserLP();
+ }
+ }
}
/**
@@ -7354,9 +7392,19 @@
* If the main user is a permanent admin user it can't be deleted
* or downgraded to non-admin status.
*/
- private static boolean isMainUserPermanentAdmin() {
+ public boolean isMainUserPermanentAdmin() {
return Resources.getSystem()
- .getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin);
+ .getBoolean(R.bool.config_isMainUserPermanentAdmin);
+ }
+
+ /**
+ * Returns true if {@link com.android.internal.R.bool#config_canSwitchToHeadlessSystemUser}
+ * is true. If allowed, headless system user can run in the foreground even though
+ * it is not a full user.
+ */
+ public boolean canSwitchToHeadlessSystemUser() {
+ return Resources.getSystem()
+ .getBoolean(R.bool.config_canSwitchToHeadlessSystemUser);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
index eed2a78..98b24ea 100644
--- a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
@@ -150,6 +150,10 @@
return runIsUserVisible();
case "get-main-user":
return runGetMainUserId();
+ case "can-switch-to-headless-system-user":
+ return canSwitchToHeadlessSystemUser();
+ case "is-main-user-permanent-admin":
+ return isMainUserPermanentAdmin();
default:
return handleDefaultCommands(cmd);
}
@@ -532,6 +536,20 @@
return 0;
}
+ private int canSwitchToHeadlessSystemUser() {
+ PrintWriter pw = getOutPrintWriter();
+ boolean canSwitchToHeadlessSystemUser = mService.canSwitchToHeadlessSystemUser();
+ pw.println(canSwitchToHeadlessSystemUser);
+ return 0;
+ }
+
+ private int isMainUserPermanentAdmin() {
+ PrintWriter pw = getOutPrintWriter();
+ boolean isMainUserPermanentAdmin = mService.isMainUserPermanentAdmin();
+ pw.println(isMainUserPermanentAdmin);
+ return 0;
+ }
+
/**
* Gets the {@link UserManager} associated with the context of the given user.
*/
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index 3f7502b..f87f50a 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -42,6 +42,7 @@
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
+import android.util.Log;
import android.util.SparseIntArray;
import android.view.Display;
@@ -55,6 +56,8 @@
import com.android.server.utils.Slogf;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -77,11 +80,11 @@
*/
public final class UserVisibilityMediator implements Dumpable {
- private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
- private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
-
private static final String TAG = UserVisibilityMediator.class.getSimpleName();
+ private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
+
private static final String PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
@@ -98,7 +101,7 @@
})
public @interface SecondaryDisplayMappingStatus {}
- // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
+ // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
@VisibleForTesting
static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM;
@@ -132,10 +135,23 @@
private final SparseIntArray mExtraDisplaysAssignedToUsers;
/**
- * Mapping from each started user to its profile group.
+ * Mapping of each user that started visible (key) to its profile group id (value).
+ *
+ * <p>It's used to determine not just if the user is visible, but also
+ * {@link #isProfile(int, int) if it's a profile}.
*/
@GuardedBy("mLock")
- private final SparseIntArray mStartedProfileGroupIds = new SparseIntArray();
+ private final SparseIntArray mStartedVisibleProfileGroupIds = new SparseIntArray();
+
+ /**
+ * List of profiles that have explicitly started invisible.
+ *
+ * <p>Only used for debugging purposes (and set when {@link #DBG} is {@code true}), hence we
+ * don't care about autoboxing.
+ */
+ @GuardedBy("mLock")
+ @Nullable
+ private final List<Integer> mStartedInvisibleProfileUserIds;
/**
* Handler user to call listeners
@@ -164,9 +180,14 @@
mUsersAssignedToDisplayOnStart = null;
mExtraDisplaysAssignedToUsers = null;
}
+ mStartedInvisibleProfileUserIds = DBG ? new ArrayList<>(4) : null;
mHandler = handler;
- // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
- mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
+ // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
+ mStartedVisibleProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
+
+ if (DBG) {
+ Slogf.i(TAG, "UserVisibilityMediator created with DBG on");
+ }
}
/**
@@ -177,6 +198,8 @@
int displayId) {
Preconditions.checkArgument(!isSpecialUserId(userId), "user id cannot be generic: %d",
userId);
+ validateUserStartMode(userStartMode);
+
// This method needs to perform 4 actions:
//
// 1. Check if the user can be started given the provided arguments
@@ -224,14 +247,29 @@
visibleUsersBefore = getVisibleUsers();
- // Set current user / profiles state
- if (userStartMode == USER_START_MODE_FOREGROUND) {
- mCurrentUserId = userId;
+ // Set current user / started users state
+ switch (userStartMode) {
+ case USER_START_MODE_FOREGROUND:
+ mCurrentUserId = userId;
+ // Fallthrough
+ case USER_START_MODE_BACKGROUND_VISIBLE:
+ if (DBG) {
+ Slogf.d(TAG, "adding visible user / profile group id mapping (%d -> %d)",
+ userId, profileGroupId);
+ }
+ mStartedVisibleProfileGroupIds.put(userId, profileGroupId);
+ break;
+ case USER_START_MODE_BACKGROUND:
+ if (mStartedInvisibleProfileUserIds != null
+ && isProfile(userId, profileGroupId)) {
+ Slogf.d(TAG, "adding user %d to list of invisible profiles", userId);
+ mStartedInvisibleProfileUserIds.add(userId);
+ }
+ break;
+ default:
+ Slogf.wtf(TAG, "invalid userStartMode passed to assignUserToDisplayOnStart: "
+ + "%d", userStartMode);
}
- if (DBG) {
- Slogf.d(TAG, "adding user / profile mapping (%d -> %d)", userId, profileGroupId);
- }
- mStartedProfileGroupIds.put(userId, profileGroupId);
// Set user / display state
switch (mappingResult) {
@@ -297,38 +335,44 @@
boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
if (displayId != DEFAULT_DISPLAY) {
if (foreground) {
- Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
+ Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot start "
+ "foreground user on secondary display", userId, profileGroupId,
- foreground, displayId);
+ userStartModeToString(userStartMode), displayId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
if (!mVisibleBackgroundUsersEnabled) {
- Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: called on "
+ Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: called on "
+ "device that doesn't support multiple users on multiple displays",
- userId, profileGroupId, foreground, displayId);
+ userId, profileGroupId, userStartModeToString(userStartMode), displayId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
}
if (isProfile(userId, profileGroupId)) {
if (displayId != DEFAULT_DISPLAY) {
- Slogf.w(TAG, "canStartUserLocked(%d, %d, %b, %d) failed: cannot start profile user "
- + "on secondary display", userId, profileGroupId, foreground,
- displayId);
+ Slogf.w(TAG, "canStartUserLocked(%d, %d, %s, %d) failed: cannot start profile user "
+ + "on secondary display", userId, profileGroupId,
+ userStartModeToString(userStartMode), displayId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
- if (foreground) {
- Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user in "
- + "foreground", userId, profileGroupId, foreground, displayId);
- return USER_ASSIGNMENT_RESULT_FAILURE;
- } else {
- boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
- if (DBG) {
- Slogf.d(TAG, "parent visible on display: %b", isParentVisibleOnDisplay);
- }
- return isParentVisibleOnDisplay
- ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
- : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
+ switch (userStartMode) {
+ case USER_START_MODE_FOREGROUND:
+ Slogf.w(TAG, "startUser(%d, %d, %s, %d) failed: cannot start profile user in "
+ + "foreground", userId, profileGroupId,
+ userStartModeToString(userStartMode), displayId);
+ return USER_ASSIGNMENT_RESULT_FAILURE;
+ case USER_START_MODE_BACKGROUND_VISIBLE:
+ boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
+ if (!isParentVisibleOnDisplay) {
+ Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot"
+ + " start profile user visible when its parent is not visible in "
+ + "that display", userId, profileGroupId,
+ userStartModeToString(userStartMode), displayId);
+ return USER_ASSIGNMENT_RESULT_FAILURE;
+ }
+ return USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
+ case USER_START_MODE_BACKGROUND:
+ return USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
}
} else if (mUsersAssignedToDisplayOnStart != null
&& isUserAssignedToDisplayOnStartLocked(userId, displayId)) {
@@ -353,8 +397,9 @@
if (mVisibleBackgroundUserOnDefaultDisplayAllowed
&& userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
- if (userStartedOnDefaultDisplay != USER_NULL) {
- Slogf.w(TAG, "getUserVisibilityOnStartLocked(): cannot start user %d visible on"
+ if (userStartedOnDefaultDisplay != USER_NULL
+ && userStartedOnDefaultDisplay != profileGroupId) {
+ Slogf.w(TAG, "canAssignUserToDisplayLocked(): cannot start user %d visible on"
+ " default display because user %d already did so", userId,
userStartedOnDefaultDisplay);
return SECONDARY_DISPLAY_MAPPING_FAILED;
@@ -468,7 +513,7 @@
userId, displayId);
return false;
}
- if (isStartedProfile(userId)) {
+ if (isStartedVisibleProfileLocked(userId)) {
Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
userId, displayId);
return false;
@@ -556,10 +601,14 @@
@GuardedBy("mLock")
private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
if (DBG) {
- Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
- mStartedProfileGroupIds);
+ Slogf.d(TAG, "Removing %d from mStartedVisibleProfileGroupIds (%s)", userId,
+ mStartedVisibleProfileGroupIds);
}
- mStartedProfileGroupIds.delete(userId);
+ mStartedVisibleProfileGroupIds.delete(userId);
+ if (mStartedInvisibleProfileUserIds != null) {
+ Slogf.d(TAG, "Removing %d from list of invisible profiles", userId);
+ mStartedInvisibleProfileUserIds.remove(Integer.valueOf(userId));
+ }
if (!mVisibleBackgroundUsersEnabled) {
// Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
@@ -589,7 +638,8 @@
* See {@link UserManagerInternal#isUserVisible(int)}.
*/
public boolean isUserVisible(@UserIdInt int userId) {
- // First check current foreground user and their profiles (on main display)
+ // For optimization (as most devices don't support visible background users), check for
+ // current foreground user and their profiles first
if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
if (VERBOSE) {
Slogf.v(TAG, "isUserVisible(%d): true to current user or profile", userId);
@@ -598,19 +648,31 @@
}
if (!mVisibleBackgroundUsersEnabled) {
- if (DBG) {
- Slogf.d(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
+ if (VERBOSE) {
+ Slogf.v(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
+ " device doesn't support visible background users", userId);
}
return false;
}
- boolean visible;
+
synchronized (mLock) {
- visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
+ int profileGroupId;
+ synchronized (mLock) {
+ profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
+ }
+ if (isProfile(userId, profileGroupId)) {
+ return isUserAssignedToDisplayOnStartLocked(profileGroupId);
+ }
+ return isUserAssignedToDisplayOnStartLocked(userId);
}
- if (DBG) {
- Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
+ }
+
+ @GuardedBy("mLock")
+ private boolean isUserAssignedToDisplayOnStartLocked(@UserIdInt int userId) {
+ boolean visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
+ if (VERBOSE) {
+ Slogf.v(TAG, "isUserAssignedToDisplayOnStartLocked(%d): %b", userId, visible);
}
return visible;
}
@@ -640,7 +702,8 @@
return false;
}
- // Current user is always visible on:
+ // For optimization (as most devices don't support visible background users), check for
+ // current user and profile first. Current user is always visible on:
// - Default display
// - Secondary displays when device doesn't support visible bg users
// - Or when explicitly added (which is checked below)
@@ -662,16 +725,28 @@
}
synchronized (mLock) {
- if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
- // User assigned to display on start
- return true;
+ int profileGroupId;
+ synchronized (mLock) {
+ profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
}
-
- // Check for extra display assignment
- return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
+ if (isProfile(userId, profileGroupId)) {
+ return isFullUserVisibleOnBackgroundLocked(profileGroupId, displayId);
+ }
+ return isFullUserVisibleOnBackgroundLocked(userId, displayId);
}
}
+ // NOTE: it doesn't check if the userId is a full user, it's up to the caller to check that
+ @GuardedBy("mLock")
+ private boolean isFullUserVisibleOnBackgroundLocked(@UserIdInt int userId, int displayId) {
+ if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
+ // User assigned to display on start
+ return true;
+ }
+ // Check for extra display assignment
+ return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
+ }
+
/**
* See {@link UserManagerInternal#getDisplayAssignedToUser(int)}.
*/
@@ -737,7 +812,7 @@
continue;
}
int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
- if (!isStartedProfile(userId)) {
+ if (!isStartedVisibleProfileLocked(userId)) {
return userId;
} else if (DBG) {
Slogf.d(TAG, "getUserAssignedToDisplay(%d): skipping user %d because it's "
@@ -770,8 +845,8 @@
// number of users is too small, the gain is probably not worth the increase on complexity.
IntArray visibleUsers = new IntArray();
synchronized (mLock) {
- for (int i = 0; i < mStartedProfileGroupIds.size(); i++) {
- int userId = mStartedProfileGroupIds.keyAt(i);
+ for (int i = 0; i < mStartedVisibleProfileGroupIds.size(); i++) {
+ int userId = mStartedVisibleProfileGroupIds.keyAt(i);
if (isUserVisible(userId)) {
visibleUsers.add(userId);
}
@@ -804,7 +879,7 @@
}
}
- // TODO(b/242195409): remove this method if not needed anymore
+ // TODO(b/266158156): remove this method if not needed anymore
/**
* Nofify all listeners that the system user visibility changed.
*/
@@ -866,6 +941,9 @@
ipw.println("UserVisibilityMediator");
ipw.increaseIndent();
+ ipw.print("DBG: ");
+ ipw.println(DBG);
+
synchronized (mLock) {
ipw.print("Current user id: ");
ipw.println(mCurrentUserId);
@@ -873,8 +951,12 @@
ipw.print("Visible users: ");
ipw.println(getVisibleUsers());
- dumpSparseIntArray(ipw, mStartedProfileGroupIds, "started user / profile group",
- "u", "pg");
+ dumpSparseIntArray(ipw, mStartedVisibleProfileGroupIds,
+ "started visible user / profile group", "u", "pg");
+ if (mStartedInvisibleProfileUserIds != null) {
+ ipw.print("Profiles started invisible: ");
+ ipw.println(mStartedInvisibleProfileUserIds);
+ }
ipw.print("Supports visible background users on displays: ");
ipw.println(mVisibleBackgroundUsersEnabled);
@@ -982,22 +1064,25 @@
if (mCurrentUserId == userId) {
return true;
}
- return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID) == mCurrentUserId;
+ return mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID)
+ == mCurrentUserId;
}
}
- private boolean isStartedProfile(@UserIdInt int userId) {
- int profileGroupId;
- synchronized (mLock) {
- profileGroupId = mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
- }
+ @GuardedBy("mLock")
+ private boolean isStartedVisibleProfileLocked(@UserIdInt int userId) {
+ int profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
return isProfile(userId, profileGroupId);
}
- private @UserIdInt int getStartedProfileGroupId(@UserIdInt int userId) {
- synchronized (mLock) {
- return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
+ private void validateUserStartMode(@UserStartMode int userStartMode) {
+ switch (userStartMode) {
+ case USER_START_MODE_FOREGROUND:
+ case USER_START_MODE_BACKGROUND:
+ case USER_START_MODE_BACKGROUND_VISIBLE:
+ return;
}
+ throw new IllegalArgumentException("Invalid user start mode: " + userStartMode);
}
private static String secondaryDisplayMappingStatusToString(
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index 977fab1..fac681a 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -807,10 +807,10 @@
}
}
- private abstract static class MimeGroupsAwareIntentResolver<F extends ParsedComponent>
- extends IntentResolver<Pair<F, ParsedIntentInfo>, ResolveInfo> {
- private final ArrayMap<String, Pair<F, ParsedIntentInfo>[]> mMimeGroupToFilter =
- new ArrayMap<>();
+ private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
+ extends ParsedComponent, ParsedIntentInfo>, R>
+ extends IntentResolver<F, R> {
+ private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
private boolean mIsUpdatingMimeGroup = false;
@NonNull
@@ -822,7 +822,7 @@
}
// Copy constructor used in creating snapshots
- MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F> orig,
+ MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig,
@NonNull UserManagerService userManager) {
mUserManager = userManager;
copyFrom(orig);
@@ -831,7 +831,7 @@
}
@Override
- public void addFilter(@Nullable PackageDataSnapshot snapshot, Pair<F, ParsedIntentInfo> f) {
+ public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
IntentFilter intentFilter = getIntentFilter(f);
// We assume Computer is available for this class and all subclasses. Because this class
// uses subclass method override to handle logic, the Computer parameter must be in the
@@ -846,7 +846,7 @@
}
@Override
- protected void removeFilterInternal(Pair<F, ParsedIntentInfo> f) {
+ protected void removeFilterInternal(F f) {
IntentFilter intentFilter = getIntentFilter(f);
if (!mIsUpdatingMimeGroup) {
unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
@@ -857,86 +857,6 @@
intentFilter.clearDynamicDataTypes();
}
- @Override
- public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
- String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId) {
- if (!mUserManager.exists(userId)) return null;
- long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
- return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, callingUid,
- userId, flags);
- }
-
- List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
- String resolvedType, long flags, int callingUid, int userId) {
- if (!mUserManager.exists(userId)) return null;
- return super.queryIntent(computer, intent, resolvedType,
- (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, callingUid, userId, flags);
- }
-
- List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
- String resolvedType, long flags, List<F> packageComponents,
- int callingUid, int userId) {
- if (!mUserManager.exists(userId)) {
- return null;
- }
- if (packageComponents == null) {
- return Collections.emptyList();
- }
- final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
- final int componentsSize = packageComponents.size();
- ArrayList<Pair<F, ParsedIntentInfo>[]> listCut = new ArrayList<>(componentsSize);
-
- List<ParsedIntentInfo> intentFilters;
- for (int i = 0; i < componentsSize; ++i) {
- F component = packageComponents.get(i);
- intentFilters = component.getIntents();
- if (!intentFilters.isEmpty()) {
- Pair<F, ParsedIntentInfo>[] array = newArray(intentFilters.size());
- for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
- array[arrayIndex] = Pair.create(component, intentFilters.get(arrayIndex));
- }
- listCut.add(array);
- }
- }
- return super.queryIntentFromList(computer, intent, resolvedType,
- defaultOnly, listCut, callingUid, userId, flags);
- }
-
- @Override
- protected boolean isPackageForFilter(String packageName, Pair<F, ParsedIntentInfo> info) {
- return packageName.equals(info.first.getPackageName());
- }
-
- @Override
- protected void sortResults(List<ResolveInfo> results) {
- results.sort(RESOLVE_PRIORITY_SORTER);
- }
-
- @Override
- protected void filterResults(@NonNull Computer computer, @NonNull Intent intent,
- List<ResolveInfo> results) {
- if (intent.getAction() != null) return;
- // When the resolved component is targeting U+, block null action intents
- for (int i = results.size() - 1; i >= 0; --i) {
- if (computer.isChangeEnabled(IntentFilter.BLOCK_NULL_ACTION_INTENTS,
- results.get(i).getComponentInfo().applicationInfo)) {
- results.remove(i);
- }
- }
- }
-
- @Override
- protected Pair<F, ParsedIntentInfo>[] newArray(int size) {
- //noinspection unchecked
- return (Pair<F, ParsedIntentInfo>[]) new Pair<?, ?>[size];
- }
-
- @Override
- protected IntentFilter getIntentFilter(
- @NonNull Pair<F, ParsedIntentInfo> input) {
- return input.second.getIntentFilter();
- }
-
/**
* Updates MIME group by applying changes to all IntentFilters
* that contain the group and repopulating m*ToFilter maps accordingly
@@ -947,12 +867,12 @@
*/
public boolean updateMimeGroup(@NonNull Computer computer, String packageName,
String mimeGroup) {
- Pair<F, ParsedIntentInfo>[] filters = mMimeGroupToFilter.get(mimeGroup);
+ F[] filters = mMimeGroupToFilter.get(mimeGroup);
int n = filters != null ? filters.length : 0;
mIsUpdatingMimeGroup = true;
boolean hasChanges = false;
- Pair<F, ParsedIntentInfo> filter;
+ F filter;
for (int i = 0; i < n && (filter = filters[i]) != null; i++) {
if (isPackageForFilter(packageName, filter)) {
hasChanges |= updateFilter(computer, filter);
@@ -962,7 +882,7 @@
return hasChanges;
}
- private boolean updateFilter(@NonNull Computer computer, Pair<F, ParsedIntentInfo> f) {
+ private boolean updateFilter(@NonNull Computer computer, F f) {
IntentFilter filter = getIntentFilter(f);
List<String> oldTypes = filter.dataTypes();
removeFilter(f);
@@ -987,7 +907,7 @@
return first.equals(second);
}
- private void applyMimeGroups(@NonNull Computer computer, Pair<F, ParsedIntentInfo> f) {
+ private void applyMimeGroups(@NonNull Computer computer, F f) {
IntentFilter filter = getIntentFilter(f);
for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
@@ -1011,8 +931,8 @@
}
@Override
- protected boolean isFilterStopped(@NonNull Computer computer,
- Pair<F, ParsedIntentInfo> filter, @UserIdInt int userId) {
+ protected boolean isFilterStopped(@NonNull Computer computer, F filter,
+ @UserIdInt int userId) {
if (!mUserManager.exists(userId)) {
return true;
}
@@ -1028,7 +948,7 @@
}
public static class ActivityIntentResolver
- extends MimeGroupsAwareIntentResolver<ParsedActivity> {
+ extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
@NonNull
private UserNeedsBadgingCache mUserNeedsBadging;
@@ -1049,6 +969,53 @@
mUserNeedsBadging = userNeedsBadgingCache;
}
+ @Override
+ public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+ String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+ if (!mUserManager.exists(userId)) return null;
+ long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
+ return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+ }
+
+ List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+ String resolvedType, long flags, int userId) {
+ if (!mUserManager.exists(userId)) {
+ return null;
+ }
+ return super.queryIntent(computer, intent, resolvedType,
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+ }
+
+ List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+ String resolvedType, long flags, List<ParsedActivity> packageActivities,
+ int userId) {
+ if (!mUserManager.exists(userId)) {
+ return null;
+ }
+ if (packageActivities == null) {
+ return Collections.emptyList();
+ }
+ final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+ final int activitiesSize = packageActivities.size();
+ ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut =
+ new ArrayList<>(activitiesSize);
+
+ List<ParsedIntentInfo> intentFilters;
+ for (int i = 0; i < activitiesSize; ++i) {
+ ParsedActivity activity = packageActivities.get(i);
+ intentFilters = activity.getIntents();
+ if (!intentFilters.isEmpty()) {
+ Pair<ParsedActivity, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+ for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+ array[arrayIndex] = Pair.create(activity, intentFilters.get(arrayIndex));
+ }
+ listCut.add(array);
+ }
+ }
+ return super.queryIntentFromList(computer, intent, resolvedType,
+ defaultOnly, listCut, userId, flags);
+ }
+
protected void addActivity(@NonNull Computer computer, ParsedActivity a, String type,
List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
mActivities.put(a.getComponentName(), a);
@@ -1105,6 +1072,18 @@
return true;
}
+ @Override
+ protected Pair<ParsedActivity, ParsedIntentInfo>[] newArray(int size) {
+ //noinspection unchecked
+ return (Pair<ParsedActivity, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+ }
+
+ @Override
+ protected boolean isPackageForFilter(String packageName,
+ Pair<ParsedActivity, ParsedIntentInfo> info) {
+ return packageName.equals(info.first.getPackageName());
+ }
+
private void log(String reason, ParsedIntentInfo info, int match,
int userId) {
Slog.w(TAG, reason
@@ -1220,6 +1199,11 @@
}
@Override
+ protected void sortResults(List<ResolveInfo> results) {
+ results.sort(RESOLVE_PRIORITY_SORTER);
+ }
+
+ @Override
protected void dumpFilter(PrintWriter out, String prefix,
Pair<ParsedActivity, ParsedIntentInfo> pair) {
ParsedActivity activity = pair.first;
@@ -1253,6 +1237,12 @@
out.println();
}
+ @Override
+ protected IntentFilter getIntentFilter(
+ @NonNull Pair<ParsedActivity, ParsedIntentInfo> input) {
+ return input.second.getIntentFilter();
+ }
+
protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
return pkg.getActivities();
}
@@ -1288,7 +1278,7 @@
}
public static final class ProviderIntentResolver
- extends MimeGroupsAwareIntentResolver<ParsedProvider> {
+ extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
// Default constructor
ProviderIntentResolver(@NonNull UserManagerService userManager) {
super(userManager);
@@ -1301,6 +1291,57 @@
mProviders.putAll(orig.mProviders);
}
+ @Override
+ public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+ String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+ if (!mUserManager.exists(userId)) {
+ return null;
+ }
+ long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+ return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+ }
+
+ @Nullable
+ List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+ String resolvedType, long flags, int userId) {
+ if (!mUserManager.exists(userId)) {
+ return null;
+ }
+ return super.queryIntent(computer, intent, resolvedType,
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+ }
+
+ @Nullable
+ List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+ String resolvedType, long flags, List<ParsedProvider> packageProviders,
+ int userId) {
+ if (!mUserManager.exists(userId)) {
+ return null;
+ }
+ if (packageProviders == null) {
+ return Collections.emptyList();
+ }
+ final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+ final int providersSize = packageProviders.size();
+ ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut =
+ new ArrayList<>(providersSize);
+
+ List<ParsedIntentInfo> intentFilters;
+ for (int i = 0; i < providersSize; ++i) {
+ ParsedProvider provider = packageProviders.get(i);
+ intentFilters = provider.getIntents();
+ if (!intentFilters.isEmpty()) {
+ Pair<ParsedProvider, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+ for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+ array[arrayIndex] = Pair.create(provider, intentFilters.get(arrayIndex));
+ }
+ listCut.add(array);
+ }
+ }
+ return super.queryIntentFromList(computer, intent, resolvedType,
+ defaultOnly, listCut, userId, flags);
+ }
+
void addProvider(@NonNull Computer computer, ParsedProvider p) {
if (mProviders.containsKey(p.getComponentName())) {
Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
@@ -1361,6 +1402,18 @@
}
@Override
+ protected Pair<ParsedProvider, ParsedIntentInfo>[] newArray(int size) {
+ //noinspection unchecked
+ return (Pair<ParsedProvider, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+ }
+
+ @Override
+ protected boolean isPackageForFilter(String packageName,
+ Pair<ParsedProvider, ParsedIntentInfo> info) {
+ return packageName.equals(info.first.getPackageName());
+ }
+
+ @Override
protected ResolveInfo newResult(@NonNull Computer computer,
Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId,
long customFlags) {
@@ -1426,6 +1479,11 @@
}
@Override
+ protected void sortResults(List<ResolveInfo> results) {
+ results.sort(RESOLVE_PRIORITY_SORTER);
+ }
+
+ @Override
protected void dumpFilter(PrintWriter out, String prefix,
Pair<ParsedProvider, ParsedIntentInfo> pair) {
ParsedProvider provider = pair.first;
@@ -1460,11 +1518,17 @@
out.println();
}
+ @Override
+ protected IntentFilter getIntentFilter(
+ @NonNull Pair<ParsedProvider, ParsedIntentInfo> input) {
+ return input.second.getIntentFilter();
+ }
+
final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
}
public static final class ServiceIntentResolver
- extends MimeGroupsAwareIntentResolver<ParsedService> {
+ extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
// Default constructor
ServiceIntentResolver(@NonNull UserManagerService userManager) {
super(userManager);
@@ -1477,6 +1541,50 @@
mServices.putAll(orig.mServices);
}
+ @Override
+ public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+ String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+ if (!mUserManager.exists(userId)) {
+ return null;
+ }
+ long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+ return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+ }
+
+ List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+ String resolvedType, long flags, int userId) {
+ if (!mUserManager.exists(userId)) return null;
+ return super.queryIntent(computer, intent, resolvedType,
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+ }
+
+ List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+ String resolvedType, long flags, List<ParsedService> packageServices, int userId) {
+ if (!mUserManager.exists(userId)) return null;
+ if (packageServices == null) {
+ return Collections.emptyList();
+ }
+ final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+ final int servicesSize = packageServices.size();
+ ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut =
+ new ArrayList<>(servicesSize);
+
+ List<ParsedIntentInfo> intentFilters;
+ for (int i = 0; i < servicesSize; ++i) {
+ ParsedService service = packageServices.get(i);
+ intentFilters = service.getIntents();
+ if (intentFilters.size() > 0) {
+ Pair<ParsedService, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+ for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+ array[arrayIndex] = Pair.create(service, intentFilters.get(arrayIndex));
+ }
+ listCut.add(array);
+ }
+ }
+ return super.queryIntentFromList(computer, intent, resolvedType,
+ defaultOnly, listCut, userId, flags);
+ }
+
void addService(@NonNull Computer computer, ParsedService s) {
mServices.put(s.getComponentName(), s);
if (DEBUG_SHOW_INFO) {
@@ -1532,6 +1640,18 @@
}
@Override
+ protected Pair<ParsedService, ParsedIntentInfo>[] newArray(int size) {
+ //noinspection unchecked
+ return (Pair<ParsedService, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+ }
+
+ @Override
+ protected boolean isPackageForFilter(String packageName,
+ Pair<ParsedService, ParsedIntentInfo> info) {
+ return packageName.equals(info.first.getPackageName());
+ }
+
+ @Override
protected ResolveInfo newResult(@NonNull Computer computer,
Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId,
long customFlags) {
@@ -1590,6 +1710,11 @@
}
@Override
+ protected void sortResults(List<ResolveInfo> results) {
+ results.sort(RESOLVE_PRIORITY_SORTER);
+ }
+
+ @Override
protected void dumpFilter(PrintWriter out, String prefix,
Pair<ParsedService, ParsedIntentInfo> pair) {
ParsedService service = pair.first;
@@ -1627,6 +1752,12 @@
out.println();
}
+ @Override
+ protected IntentFilter getIntentFilter(
+ @NonNull Pair<ParsedService, ParsedIntentInfo> input) {
+ return input.second.getIntentFilter();
+ }
+
// Keys are String (activity class name), values are Activity.
final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
}
@@ -1690,8 +1821,7 @@
}
@Override
- protected void filterResults(@NonNull Computer computer,
- @NonNull Intent intent, List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
+ protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
// only do work if ordering is enabled [most of the time it won't be]
if (mOrderResult.size() == 0) {
return;
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
index 7f88660..b8e4c8d 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
@@ -55,12 +55,12 @@
@Nullable
List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+ @Nullable String resolvedType, long flags, @UserIdInt int userId);
@Nullable
List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
- int callingUid, @UserIdInt int userId);
+ @UserIdInt int userId);
@Nullable
ProviderInfo queryProvider(@NonNull Computer computer, @NonNull String authority, long flags,
@@ -68,12 +68,12 @@
@Nullable
List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+ @Nullable String resolvedType, long flags, @UserIdInt int userId);
@Nullable
List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
- int callingUid, @UserIdInt int userId);
+ @UserIdInt int userId);
@Nullable
List<ProviderInfo> queryProviders(@NonNull Computer computer, @Nullable String processName,
@@ -81,21 +81,21 @@
@Nullable
List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+ @Nullable String resolvedType, long flags, @UserIdInt int userId);
@Nullable
List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
- int callingUid, @UserIdInt int userId);
+ @UserIdInt int userId);
@Nullable
List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+ @Nullable String resolvedType, long flags, @UserIdInt int userId);
@Nullable
List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
- int callingUid, @UserIdInt int userId);
+ @UserIdInt int userId);
void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
@NonNull List<ProviderInfo> outInfo, boolean safeMode, @UserIdInt int userId);
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
index 6899924..9115775 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
@@ -126,17 +126,17 @@
@Nullable
@Override
public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, int userId) {
- return mActivities.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+ @Nullable String resolvedType, long flags, int userId) {
+ return mActivities.queryIntent(computer, intent, resolvedType, flags, userId);
}
@Nullable
@Override
public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
- int callingUid, int userId) {
+ int userId) {
return mActivities.queryIntentForPackage(computer, intent, resolvedType, flags, activities,
- callingUid, userId);
+ userId);
}
@Nullable
@@ -168,17 +168,17 @@
@Nullable
@Override
public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, int userId) {
- return mProviders.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+ @Nullable String resolvedType, long flags, int userId) {
+ return mProviders.queryIntent(computer, intent, resolvedType, flags, userId);
}
@Nullable
@Override
public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
- int callingUid, @UserIdInt int userId) {
+ @UserIdInt int userId) {
return mProviders.queryIntentForPackage(computer, intent, resolvedType, flags, providers,
- callingUid, userId);
+ userId);
}
@Nullable
@@ -241,33 +241,33 @@
@Nullable
@Override
public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, int userId) {
- return mReceivers.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+ @Nullable String resolvedType, long flags, int userId) {
+ return mReceivers.queryIntent(computer, intent, resolvedType, flags, userId);
}
@Nullable
@Override
public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
- int callingUid, @UserIdInt int userId) {
+ @UserIdInt int userId) {
return mReceivers.queryIntentForPackage(computer, intent, resolvedType, flags, receivers,
- callingUid, userId);
+ userId);
}
@Nullable
@Override
public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
- return mServices.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+ @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+ return mServices.queryIntent(computer, intent, resolvedType, flags, userId);
}
@Nullable
@Override
public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
- int callingUid, @UserIdInt int userId) {
+ @UserIdInt int userId) {
return mServices.queryIntentForPackage(computer, intent, resolvedType, flags, services,
- callingUid, userId);
+ userId);
}
@Override
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
index 5bfb135..0c84f4c 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
@@ -92,9 +92,9 @@
@Nullable
@Override
public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+ @Nullable String resolvedType, long flags, @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryActivities(computer, intent, resolvedType, flags, callingUid, userId);
+ return super.queryActivities(computer, intent, resolvedType, flags, userId);
}
}
@@ -102,10 +102,9 @@
@Override
public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
- int callingUid, @UserIdInt int userId) {
+ @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryActivities(computer, intent, resolvedType, flags, activities,
- callingUid, userId);
+ return super.queryActivities(computer, intent, resolvedType, flags, activities, userId);
}
}
@@ -121,9 +120,9 @@
@Nullable
@Override
public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+ @Nullable String resolvedType, long flags, @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryProviders(computer, intent, resolvedType, flags, callingUid, userId);
+ return super.queryProviders(computer, intent, resolvedType, flags, userId);
}
}
@@ -131,10 +130,9 @@
@Override
public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
- int callingUid, @UserIdInt int userId) {
+ @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryProviders(computer, intent, resolvedType, flags, providers,
- callingUid, userId);
+ return super.queryProviders(computer, intent, resolvedType, flags, providers, userId);
}
}
@@ -151,9 +149,9 @@
@Nullable
@Override
public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+ @Nullable String resolvedType, long flags, @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryReceivers(computer, intent, resolvedType, flags, callingUid, userId);
+ return super.queryReceivers(computer, intent, resolvedType, flags, userId);
}
}
@@ -161,19 +159,18 @@
@Override
public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
- int callingUid, @UserIdInt int userId) {
+ @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryReceivers(computer, intent, resolvedType, flags, receivers,
- callingUid, userId);
+ return super.queryReceivers(computer, intent, resolvedType, flags, receivers, userId);
}
}
@Nullable
@Override
public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
- @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+ @Nullable String resolvedType, long flags, @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryServices(computer, intent, resolvedType, flags, callingUid, userId);
+ return super.queryServices(computer, intent, resolvedType, flags, userId);
}
}
@@ -181,10 +178,9 @@
@Override
public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
@Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
- int callingUid, @UserIdInt int userId) {
+ @UserIdInt int userId) {
synchronized (mLock) {
- return super.queryServices(computer, intent, resolvedType, flags, services, callingUid,
- userId);
+ return super.queryServices(computer, intent, resolvedType, flags, services, userId);
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 37877cf..92dd95a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -68,6 +68,7 @@
import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
+import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -190,6 +191,7 @@
import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
@@ -332,6 +334,10 @@
static final int TRIPLE_PRESS_PRIMARY_NOTHING = 0;
static final int TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY = 1;
+ // Must match: config_searchKeyBehavior in config.xml
+ static final int SEARCH_BEHAVIOR_DEFAULT_SEARCH = 0;
+ static final int SEARCH_BEHAVIOR_TARGET_ACTIVITY = 1;
+
static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -540,6 +546,8 @@
boolean mWakeOnAssistKeyPress;
boolean mWakeOnBackKeyPress;
long mWakeUpToLastStateTimeout;
+ int mSearchKeyBehavior;
+ ComponentName mSearchKeyTargetActivity;
private boolean mHandleVolumeKeysInWM;
@@ -1394,7 +1402,18 @@
if (DEBUG_INPUT) {
Slog.d(TAG, "Executing stem primary triple press action behavior.");
}
- toggleTalkBack();
+
+ if (Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
+ /* def= */ 0, UserHandle.USER_CURRENT) == 1) {
+ /** Toggle talkback begin */
+ ComponentName componentName = getTalkbackComponent();
+ if (componentName != null && toggleTalkBack(componentName)) {
+ /** log stem triple press telemetry if it's a talkback enabled event */
+ logStemTriplePressAccessibilityTelemetry(componentName);
+ }
+ /** Toggle talkback end */
+ }
break;
}
}
@@ -1413,17 +1432,39 @@
}
}
- private void toggleTalkBack() {
- final ComponentName componentName = getTalkbackComponent();
- if (componentName == null) {
- return;
- }
-
+ /**
+ * A function that toggles talkback service
+ *
+ * @return {@code true} if talkback is enabled, {@code false} if talkback is disabled
+ */
+ private boolean toggleTalkBack(ComponentName componentName) {
final Set<ComponentName> enabledServices =
AccessibilityUtils.getEnabledServicesFromSettings(mContext, mCurrentUserId);
+ boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName);
AccessibilityUtils.setAccessibilityServiceState(mContext, componentName,
- !enabledServices.contains(componentName));
+ !isTalkbackAlreadyEnabled);
+ /** if isTalkbackAlreadyEnabled is true, then it's a disabled event so return false
+ * and if isTalkbackAlreadyEnabled is false, return true as it's an enabled event */
+ return !isTalkbackAlreadyEnabled;
+ }
+
+ /**
+ * A function that logs stem triple press accessibility telemetry
+ * If the user setup (Oobe) is not completed, set the
+ * WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE
+ * setting which will be later logged via Settings Snapshot
+ * else, log ACCESSIBILITY_SHORTCUT_REPORTED atom
+ */
+ private void logStemTriplePressAccessibilityTelemetry(ComponentName componentName) {
+ if (!AccessibilityUtils.isUserSetupCompleted(mContext)) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, 1);
+ } else {
+ AccessibilityStatsLogUtils.logAccessibilityShortcutActivated(mContext, componentName,
+ ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE,
+ /* serviceEnabled= */ true);
+ }
}
private ComponentName getTalkbackComponent() {
@@ -2139,6 +2180,12 @@
mWakeUpToLastStateTimeout = mContext.getResources().getInteger(
com.android.internal.R.integer.config_wakeUpToLastStateTimeoutMillis);
+ mSearchKeyBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_searchKeyBehavior);
+
+ mSearchKeyTargetActivity = ComponentName.unflattenFromString(
+ mContext.getResources().getString(
+ com.android.internal.R.string.config_searchKeyTargetActivity));
readConfigurationDependentBehaviors();
mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);
@@ -3161,7 +3208,19 @@
toggleNotificationPanel();
}
return key_consumed;
-
+ case KeyEvent.KEYCODE_SEARCH:
+ if (down && repeatCount == 0 && !keyguardOn()) {
+ switch(mSearchKeyBehavior) {
+ case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {
+ launchTargetSearchActivity();
+ return key_consumed;
+ }
+ case SEARCH_BEHAVIOR_DEFAULT_SEARCH:
+ default:
+ break;
+ }
+ }
+ break;
case KeyEvent.KEYCODE_SPACE:
// Handle keyboard layout switching. (META + SPACE)
if ((metaState & KeyEvent.META_META_MASK) == 0) {
@@ -6344,4 +6403,22 @@
}
}
+ private void launchTargetSearchActivity() {
+ Intent intent;
+ if (mSearchKeyTargetActivity != null) {
+ intent = new Intent();
+ intent.setComponent(mSearchKeyTargetActivity);
+ } else {
+ intent = new Intent(Intent.ACTION_WEB_SEARCH);
+ }
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ try {
+ startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ } catch (ActivityNotFoundException ignore) {
+ Slog.e(TAG, "Could not resolve activity with : "
+ + intent.getComponent().flattenToString()
+ + " name.");
+ }
+ }
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 85f1357..646dc4e 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -29,6 +29,7 @@
import com.android.internal.policy.IKeyguardService;
import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy.OnKeyguardExitResult;
+import com.android.server.wm.EventLogTags;
import java.io.PrintWriter;
@@ -255,6 +256,11 @@
public void setOccluded(boolean isOccluded, boolean notify) {
if (mKeyguardService != null && notify) {
if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ")");
+ EventLogTags.writeWmSetKeyguardOccluded(
+ isOccluded ? 1 : 0,
+ 0 /* animate */,
+ 0 /* transit */,
+ "setOccluded");
mKeyguardService.setOccluded(isOccluded, false /* animate */);
}
mKeyguardState.occluded = isOccluded;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b83d509..ea494db 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -40,7 +40,6 @@
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.SynchronousUserSwitchObserver;
import android.content.BroadcastReceiver;
@@ -317,7 +316,6 @@
private SettingsObserver mSettingsObserver;
private DreamManagerInternal mDreamManager;
private LogicalLight mAttentionLight;
- private ActivityManagerInternal mAmInternal;
private final InattentiveSleepWarningController mInattentiveSleepWarningOverlayController;
private final AmbientDisplaySuppressionController mAmbientDisplaySuppressionController;
@@ -1244,7 +1242,6 @@
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
mPolicy = getLocalService(WindowManagerPolicy.class);
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
- mAmInternal = getLocalService(ActivityManagerInternal.class);
mAttentionDetector.systemReady(mContext);
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -4088,8 +4085,9 @@
final UidState state = wakeLock.mUidState;
if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
- (mAmInternal != null && !mAmInternal.canHoldWakeLocksInDeepDoze(
- state.mUid, state.mProcState))) {
+ state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
+ state.mProcState >
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
disabled = true;
}
}
@@ -5695,6 +5693,7 @@
}
if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -5710,7 +5709,9 @@
@Override // Binder call
public void wakeUp(long eventTime, @WakeReason int reason, String details,
String opPackageName) {
- if (eventTime > mClock.uptimeMillis()) {
+ final long now = mClock.uptimeMillis();
+ if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -5762,7 +5763,9 @@
@Override // Binder call
public void nap(long eventTime) {
- if (eventTime > mClock.uptimeMillis()) {
+ final long now = mClock.uptimeMillis();
+ if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -6527,7 +6530,9 @@
@Override // Binder call
public void boostScreenBrightness(long eventTime) {
+ final long now = mClock.uptimeMillis();
if (eventTime > mClock.uptimeMillis()) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -6639,6 +6644,13 @@
}
}
+ @VisibleForTesting
+ int getPowerGroupSize() {
+ synchronized (mLock) {
+ return mPowerGroups.size();
+ }
+ }
+
@GoToSleepReason
private int getLastSleepReasonInternal() {
synchronized (mLock) {
@@ -6686,7 +6698,9 @@
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
private void goToSleepInternal(IntArray groupIds, long eventTime, int reason, int flags) {
- if (eventTime > mClock.uptimeMillis()) {
+ final long now = mClock.uptimeMillis();
+ if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index a319113..a5ca7ac 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -17,6 +17,7 @@
package com.android.server.power;
+import android.app.ActivityManagerInternal;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.IActivityManager;
@@ -25,9 +26,11 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManagerInternal;
+import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.PowerManager;
@@ -52,7 +55,6 @@
import com.android.server.LocalServices;
import com.android.server.RescueParty;
-import com.android.server.pm.PackageManagerService;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.File;
@@ -444,13 +446,6 @@
new File(CHECK_POINTS_FILE_BASENAME));
dumpCheckPointsThread.start();
- BroadcastReceiver br = new BroadcastReceiver() {
- @Override public void onReceive(Context context, Intent intent) {
- // We don't allow apps to cancel this, so ignore the result.
- actionDone();
- }
- };
-
/*
* Write a system property in case the system_server reboots before we
* get to the actual hardware restart. If that happens, we'll retry at
@@ -486,8 +481,16 @@
mActionDone = false;
Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mContext.sendOrderedBroadcastAsUser(intent,
- UserHandle.ALL, null, br, mHandler, 0, null, null);
+ final ActivityManagerInternal activityManagerInternal = LocalServices.getService(
+ ActivityManagerInternal.class);
+ activityManagerInternal.broadcastIntentWithCallback(intent,
+ new IIntentReceiver.Stub() {
+ @Override
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
+ mHandler.post(ShutdownThread.this::actionDone);
+ }
+ }, null, UserHandle.USER_ALL, null, null, null);
final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
synchronized (mActionDoneSync) {
diff --git a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
index 54f3476..e8c0e59 100644
--- a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
+++ b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
@@ -18,6 +18,7 @@
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM;
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
import android.content.Context;
import android.os.Handler;
@@ -49,6 +50,7 @@
private static final String TAG = "CpuWakeupStats";
private static final String SUBSYSTEM_ALARM_STRING = "Alarm";
+ private static final String SUBSYSTEM_ALARM_WIFI = "Wifi";
@VisibleForTesting
static final long WAKEUP_RETENTION_MS = 3 * 24 * 60 * 60_000; // 3 days.
@VisibleForTesting
@@ -74,6 +76,8 @@
switch (subsystem) {
case CPU_WAKEUP_SUBSYSTEM_ALARM:
return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__ALARM;
+ case CPU_WAKEUP_SUBSYSTEM_WIFI:
+ return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__WIFI;
}
return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__UNKNOWN;
}
@@ -425,6 +429,8 @@
switch (rawSubsystem) {
case SUBSYSTEM_ALARM_STRING:
return CPU_WAKEUP_SUBSYSTEM_ALARM;
+ case SUBSYSTEM_ALARM_WIFI:
+ return CPU_WAKEUP_SUBSYSTEM_WIFI;
}
return CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
}
@@ -433,6 +439,8 @@
switch (subsystem) {
case CPU_WAKEUP_SUBSYSTEM_ALARM:
return SUBSYSTEM_ALARM_STRING;
+ case CPU_WAKEUP_SUBSYSTEM_WIFI:
+ return SUBSYSTEM_ALARM_WIFI;
case CPU_WAKEUP_SUBSYSTEM_UNKNOWN:
return "Unknown";
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ac03808..7a73359 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -945,7 +945,9 @@
mWindowManagerInternal.removeWindowToken(mToken, false/* removeWindows */,
mDisplayId);
try {
- connection.mService.detach(mToken);
+ if (connection.mService != null) {
+ connection.mService.detach(mToken);
+ }
} catch (RemoteException e) {
Slog.w(TAG, "connection.mService.destroy() threw a RemoteException");
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 01e9522..d108f0d 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1714,4 +1714,20 @@
}
}
}
+
+ /**
+ * Returns {@code true} if the activity was explicitly requested to be launched in its
+ * current TaskFragment.
+ *
+ * @see ActivityRecord#mRequestedLaunchingTaskFragmentToken
+ */
+ public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
+ IBinder taskFragmentToken) {
+ synchronized (mGlobalLock) {
+ final ActivityRecord r = ActivityRecord.isInRootTaskLocked(activityToken);
+ if (r == null) return false;
+
+ return r.mRequestedLaunchingTaskFragmentToken == taskFragmentToken;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e62d305..9def87c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -565,6 +565,8 @@
volatile boolean inHistory;
final ActivityTaskSupervisor mTaskSupervisor;
final RootWindowContainer mRootWindowContainer;
+ // The token of the TaskFragment that this activity was requested to be launched into.
+ IBinder mRequestedLaunchingTaskFragmentToken;
// Tracking splash screen status from previous activity
boolean mSplashScreenStyleSolidColor = false;
@@ -1605,6 +1607,8 @@
if (oldParent != null) {
oldParent.cleanUpActivityReferences(this);
+ // Clear the state as this activity is removed from its old parent.
+ mRequestedLaunchingTaskFragmentToken = null;
}
if (newParent != null) {
@@ -7933,7 +7937,7 @@
}
return getTask().getConfiguration().smallestScreenWidthDp
- >= mAtmService.mLargeScreenSmallestScreenWidthDp;
+ >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
}
/**
@@ -8080,11 +8084,7 @@
return false;
}
}
- // Activity should be resizable if the task is.
- final boolean isResizeable = task != null
- ? task.isResizeable() || isResizeable()
- : isResizeable();
- return !isResizeable && (info.isFixedOrientation() || hasFixedAspectRatio())
+ return !isResizeable() && (info.isFixedOrientation() || hasFixedAspectRatio())
// The configuration of non-standard type should be enforced by system.
// {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
// added to a task, but this function is called when resolving the launch params, at
diff --git a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
index 8a4fc0db..1f7af41 100644
--- a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
+++ b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
@@ -43,7 +43,7 @@
static final String DOC_LINK = "go/android-asm";
/** Used to determine which version of the ASM logic was used in logs while we iterate */
- static final int ASM_VERSION = 5;
+ static final int ASM_VERSION = 6;
private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e990460..88d1086 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1948,9 +1948,13 @@
boolean passesAsmChecks = true;
Task sourceTask = mSourceRecord.getTask();
- // Don't allow launches into a new task if the current task is not foreground.
+ // Allow launching into a new task (or a task matching the launched activity's
+ // affinity) only if the current task is foreground or mutating its own task.
+ // The latter can happen eg. if caller uses NEW_TASK flag and the activity being
+ // launched matches affinity of source task.
if (taskToFront) {
- passesAsmChecks = sourceTask != null && sourceTask.isVisible();
+ passesAsmChecks = sourceTask != null
+ && (sourceTask.isVisible() || sourceTask == targetTask);
}
if (passesAsmChecks) {
@@ -3032,6 +3036,8 @@
int embeddingCheckResult = canEmbedActivity(mInTaskFragment, mStartActivity, task);
if (embeddingCheckResult == EMBEDDING_ALLOWED) {
newParent = mInTaskFragment;
+ mStartActivity.mRequestedLaunchingTaskFragmentToken =
+ mInTaskFragment.getFragmentToken();
} else {
// Start mStartActivity to task instead if it can't be embedded to mInTaskFragment.
sendCanNotEmbedActivityError(mInTaskFragment, embeddingCheckResult);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 18be2a3..923ca79 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -45,6 +45,7 @@
import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_CANT_SAVE_STATE;
+import static android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
import static android.content.pm.PackageManager.FEATURE_EXPANDED_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
@@ -401,6 +402,7 @@
volatile WindowProcessController mHeavyWeightProcess;
boolean mHasHeavyWeightFeature;
boolean mHasLeanbackFeature;
+ boolean mHasCompanionDeviceSetupFeature;
/** The process of the top most activity. */
volatile WindowProcessController mTopApp;
/**
@@ -607,7 +609,7 @@
* Whether the device supports non-resizable in multi windowing modes.
* -1: The device doesn't support non-resizable in multi windowing modes.
* 0: The device supports non-resizable in multi windowing modes only if this is a large
- * screen (smallest width >= {@link #mLargeScreenSmallestScreenWidthDp}).
+ * screen (smallest width >= {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}).
* 1: The device always supports non-resizable in multi windowing modes.
*/
int mSupportsNonResizableMultiWindow;
@@ -617,7 +619,8 @@
* windowing modes.
* -1: The device ignores activity min width/height when determining if it can be shown in multi
* windowing modes.
- * 0: If it is a small screen (smallest width < {@link #mLargeScreenSmallestScreenWidthDp}),
+ * 0: If it is a small screen (smallest width <
+ * {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}),
* the device compares the activity min width/height with the min multi windowing modes
* dimensions {@link #mMinPercentageMultiWindowSupportHeight} the device supports to
* determine whether the activity can be shown in multi windowing modes
@@ -645,13 +648,6 @@
*/
float mMinPercentageMultiWindowSupportWidth;
- /**
- * If the display {@link Configuration#smallestScreenWidthDp} is greater or equal to this value,
- * we will treat it as a large screen device, which will have some multi window features enabled
- * by default.
- */
- int mLargeScreenSmallestScreenWidthDp;
-
final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = new ArrayList<>();
// VR Vr2d Display Id.
@@ -859,6 +855,7 @@
final PackageManager pm = mContext.getPackageManager();
mHasHeavyWeightFeature = pm.hasSystemFeature(FEATURE_CANT_SAVE_STATE);
mHasLeanbackFeature = pm.hasSystemFeature(FEATURE_LEANBACK);
+ mHasCompanionDeviceSetupFeature = pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP);
mVrController.onSystemReady();
mRecentTasks.onSystemReadyLocked();
mTaskSupervisor.onSystemReady();
@@ -911,8 +908,6 @@
com.android.internal.R.dimen.config_minPercentageMultiWindowSupportHeight);
final float minPercentageMultiWindowSupportWidth = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_minPercentageMultiWindowSupportWidth);
- final int largeScreenSmallestScreenWidthDp = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_largeScreenSmallestScreenWidthDp);
// Transfer any global setting for forcing RTL layout, into a System Property
DisplayProperties.debug_force_rtl(forceRtl);
@@ -931,7 +926,6 @@
mRespectsActivityMinWidthHeightMultiWindow = respectsActivityMinWidthHeightMultiWindow;
mMinPercentageMultiWindowSupportHeight = minPercentageMultiWindowSupportHeight;
mMinPercentageMultiWindowSupportWidth = minPercentageMultiWindowSupportWidth;
- mLargeScreenSmallestScreenWidthDp = largeScreenSmallestScreenWidthDp;
final boolean multiWindowFormEnabled = freeformWindowManagement
|| supportsSplitScreenMultiWindow
|| supportsPictureInPicture
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index e463358..df471c5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1239,8 +1239,13 @@
return Context.DEVICE_ID_DEFAULT;
}
if (mVirtualDeviceManager == null) {
- mVirtualDeviceManager =
- mService.mContext.getSystemService(VirtualDeviceManager.class);
+ if (mService.mHasCompanionDeviceSetupFeature) {
+ mVirtualDeviceManager =
+ mService.mContext.getSystemService(VirtualDeviceManager.class);
+ }
+ if (mVirtualDeviceManager == null) {
+ return Context.DEVICE_ID_DEFAULT;
+ }
}
return mVirtualDeviceManager.getDeviceIdForDisplayId(displayId);
}
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index a229fc5..2d45dc2 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -75,6 +75,11 @@
private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
private final ArrayList<WindowContainer> mTmpCloseApps = new ArrayList<>();
+ // This will be set if the back navigation is in progress and the current transition is still
+ // running. The pending animation builder will do the animation stuff includes creating leashes,
+ // re-parenting leashes and set launch behind, etc. Will be handled when transition finished.
+ private AnimationHandler.ScheduleAnimationBuilder mPendingAnimationBuilder;
+
/**
* true if the back predictability feature is enabled
*/
@@ -305,25 +310,26 @@
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY)
&& adapter != null;
- // Only prepare animation if no leash has been created (no animation is running).
- // TODO(b/241808055): Cancel animation when preparing back animation.
- if (prepareAnimation
- && (removedWindowContainer.hasCommittedReparentToAnimationLeash()
- || removedWindowContainer.mTransitionController.inTransition())) {
- Slog.w(TAG, "Can't prepare back animation due to another animation is running.");
- prepareAnimation = false;
- }
-
if (prepareAnimation) {
- mPendingAnimation = mAnimationHandler.scheduleAnimation(backType, adapter,
- currentTask, prevTask, currentActivity, prevActivity);
- prepareAnimation = mPendingAnimation != null;
- mBackAnimationInProgress = prepareAnimation;
- if (prepareAnimation) {
- mWindowManagerService.mWindowPlacerLocked.requestTraversal();
- if (mShowWallpaper) {
- currentTask.getDisplayContent().mWallpaperController
- .adjustWallpaperWindows();
+ final AnimationHandler.ScheduleAnimationBuilder builder =
+ mAnimationHandler.prepareAnimation(backType, adapter,
+ currentTask, prevTask, currentActivity, prevActivity);
+ mBackAnimationInProgress = builder != null;
+ if (mBackAnimationInProgress) {
+ if (removedWindowContainer.hasCommittedReparentToAnimationLeash()
+ || removedWindowContainer.mTransitionController.inTransition()
+ || mWindowManagerService.mSyncEngine.hasPendingSyncSets()) {
+ ProtoLog.w(WM_DEBUG_BACK_PREVIEW,
+ "Pending back animation due to another animation is running");
+ mPendingAnimationBuilder = builder;
+ // Current transition is still running, we have to defer the hiding to the
+ // client process to prevent the unexpected relayout when handling the back
+ // animation.
+ if (prevActivity != null) {
+ prevActivity.setDeferHidingClient(true);
+ }
+ } else {
+ scheduleAnimation(builder);
}
}
}
@@ -345,6 +351,15 @@
return isWaitBackTransition() || mNavigationMonitor.isMonitoring();
}
+ private void scheduleAnimation(@NonNull AnimationHandler.ScheduleAnimationBuilder builder) {
+ mPendingAnimation = builder.build();
+ mWindowManagerService.mWindowPlacerLocked.requestTraversal();
+ if (mShowWallpaper) {
+ mWindowManagerService.getDefaultDisplayContentLocked().mWallpaperController
+ .adjustWallpaperWindows();
+ }
+ }
+
private boolean isWaitBackTransition() {
return mAnimationHandler.mComposed && mAnimationHandler.mWaitTransition;
}
@@ -526,6 +541,57 @@
mAnimationHandler.clearBackAnimateTarget(cleanupTransaction);
}
+ /**
+ * Handle the pending animation when the running transition finished.
+ * @param targets The final animation targets derived in transition.
+ */
+ boolean handleDeferredBackAnimation(@NonNull ArrayList<Transition.ChangeInfo> targets) {
+ if (!mBackAnimationInProgress || mPendingAnimationBuilder == null) {
+ return false;
+ }
+
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Handling the deferred animation after transition finished");
+
+ // Show the target surface and its parents to prevent it or its parents hidden when
+ // the transition finished.
+ // The target could be affected by transition when :
+ // Open transition -> the open target in back navigation
+ // Close transition -> the close target in back navigation.
+ boolean hasTarget = false;
+ final SurfaceControl.Transaction t =
+ mPendingAnimationBuilder.mCloseTarget.getPendingTransaction();
+ for (int i = 0; i < targets.size(); i++) {
+ final WindowContainer wc = targets.get(i).mContainer;
+ if (wc.asActivityRecord() == null && wc.asTask() == null) {
+ continue;
+ } else if (!mPendingAnimationBuilder.containTarget(wc)) {
+ continue;
+ }
+
+ hasTarget = true;
+ t.show(wc.getSurfaceControl());
+ }
+
+ if (!hasTarget) {
+ // Skip if no target participated in current finished transition.
+ Slog.w(TAG, "Finished transition didn't include the targets"
+ + " open: " + mPendingAnimationBuilder.mOpenTarget
+ + " close: " + mPendingAnimationBuilder.mCloseTarget);
+ try {
+ mPendingAnimationBuilder.mBackAnimationAdapter.getRunner().onAnimationCancelled();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ mPendingAnimationBuilder = null;
+ return false;
+ }
+
+ scheduleAnimation(mPendingAnimationBuilder);
+ mPendingAnimationBuilder = null;
+ return true;
+ }
+
/**
* Create and handling animations status for an open/close animation targets.
*/
@@ -638,6 +704,7 @@
if (open) {
return wc == mOpenAdaptor.mTarget || mOpenAdaptor.mTarget.hasChild(wc);
}
+
if (mSwitchType == TASK_SWITCH) {
return wc == mCloseAdaptor.mTarget
|| (wc.asTask() != null && wc.hasChild(mCloseAdaptor.mTarget));
@@ -841,23 +908,22 @@
}
}
- Runnable scheduleAnimation(int backType, BackAnimationAdapter adapter,
+ ScheduleAnimationBuilder prepareAnimation(int backType, BackAnimationAdapter adapter,
Task currentTask, Task previousTask, ActivityRecord currentActivity,
ActivityRecord previousActivity) {
switch (backType) {
case BackNavigationInfo.TYPE_RETURN_TO_HOME:
return new ScheduleAnimationBuilder(backType, adapter)
.setIsLaunchBehind(true)
- .setComposeTarget(currentTask, previousTask)
- .build();
+ .setComposeTarget(currentTask, previousTask);
case BackNavigationInfo.TYPE_CROSS_ACTIVITY:
return new ScheduleAnimationBuilder(backType, adapter)
.setComposeTarget(currentActivity, previousActivity)
- .setOpeningSnapshot(getActivitySnapshot(previousActivity)).build();
+ .setOpeningSnapshot(getActivitySnapshot(previousActivity));
case BackNavigationInfo.TYPE_CROSS_TASK:
return new ScheduleAnimationBuilder(backType, adapter)
.setComposeTarget(currentTask, previousTask)
- .setOpeningSnapshot(getTaskSnapshot(previousTask)).build();
+ .setOpeningSnapshot(getTaskSnapshot(previousTask));
}
return null;
}
@@ -891,6 +957,11 @@
return this;
}
+ boolean containTarget(@NonNull WindowContainer wc) {
+ return wc == mOpenTarget || wc == mCloseTarget
+ || wc.hasChild(mOpenTarget) || wc.hasChild(mCloseTarget);
+ }
+
Runnable build() {
if (mOpenTarget == null || mCloseTarget == null) {
return null;
@@ -967,49 +1038,43 @@
}
};
}
-
- private void setLaunchBehind(ActivityRecord activity) {
- if (activity == null) {
- return;
- }
- if (!activity.isVisibleRequested()) {
- activity.setVisibility(true);
- }
- activity.mLaunchTaskBehind = true;
-
- // Handle fixed rotation launching app.
- final DisplayContent dc = activity.mDisplayContent;
- dc.rotateInDifferentOrientationIfNeeded(activity);
- if (activity.hasFixedRotationTransform()) {
- // Set the record so we can recognize it to continue to update display
- // orientation if the previous activity becomes the top later.
- dc.setFixedRotationLaunchingApp(activity,
- activity.getWindowConfiguration().getRotation());
- }
-
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
- "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
- activity.mTaskSupervisor.mStoppingActivities.remove(activity);
- activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, false /* preserveWindows */, true);
- }
- private void restoreLaunchBehind(ActivityRecord activity) {
- if (activity == null) {
- return;
- }
-
- activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
-
- // Restore the launch-behind state.
- activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
- activity.mLaunchTaskBehind = false;
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
- "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
- activity);
- }
}
}
+ private static void setLaunchBehind(@NonNull ActivityRecord activity) {
+ if (!activity.isVisibleRequested()) {
+ activity.setVisibility(true);
+ }
+ activity.mLaunchTaskBehind = true;
+
+ // Handle fixed rotation launching app.
+ final DisplayContent dc = activity.mDisplayContent;
+ dc.rotateInDifferentOrientationIfNeeded(activity);
+ if (activity.hasFixedRotationTransform()) {
+ // Set the record so we can recognize it to continue to update display
+ // orientation if the previous activity becomes the top later.
+ dc.setFixedRotationLaunchingApp(activity,
+ activity.getWindowConfiguration().getRotation());
+ }
+
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
+ activity.mTaskSupervisor.mStoppingActivities.remove(activity);
+ activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
+ 0 /* configChanges */, false /* preserveWindows */, true);
+ }
+
+ private static void restoreLaunchBehind(@NonNull ActivityRecord activity) {
+ activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
+
+ // Restore the launch-behind state.
+ activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
+ activity.mLaunchTaskBehind = false;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+ activity);
+ }
+
void checkAnimationReady(WallpaperController wallpaperController) {
if (!mBackAnimationInProgress) {
return;
@@ -1039,6 +1104,7 @@
mNavigationMonitor.stopMonitor();
mBackAnimationInProgress = false;
mShowWallpaper = false;
+ mPendingAnimationBuilder = null;
}
private static TaskSnapshot getActivitySnapshot(@NonNull ActivityRecord r) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 86c4e0f..947edde 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -38,6 +38,9 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.util.RotationUtils.deltaRotation;
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.util.TypedValue.COMPLEX_UNIT_MASK;
+import static android.util.TypedValue.COMPLEX_UNIT_SHIFT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.FLAG_PRIVATE;
@@ -170,6 +173,7 @@
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
import android.graphics.Insets;
@@ -206,6 +210,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
import android.view.ContentRecordingSession;
import android.view.Display;
@@ -1684,14 +1689,16 @@
private int getMinimalTaskSizeDp() {
final Context displayConfigurationContext =
mAtmService.mContext.createConfigurationContext(getConfiguration());
- final float minimalSize =
- displayConfigurationContext.getResources().getDimension(
- R.dimen.default_minimal_size_resizable_task);
- if (Double.compare(mDisplayMetrics.density, 0.0) == 0) {
- throw new IllegalArgumentException("Display with ID=" + getDisplayId() + "has invalid "
- + "DisplayMetrics.density= 0.0");
+ final Resources res = displayConfigurationContext.getResources();
+ final TypedValue value = new TypedValue();
+ res.getValue(R.dimen.default_minimal_size_resizable_task, value, true /* resolveRefs */);
+ final int valueUnit = ((value.data >> COMPLEX_UNIT_SHIFT) & COMPLEX_UNIT_MASK);
+ if (value.type != TypedValue.TYPE_DIMENSION || valueUnit != COMPLEX_UNIT_DIP) {
+ throw new IllegalArgumentException(
+ "Resource ID #0x" + Integer.toHexString(R.dimen.default_minimal_size_resizable_task)
+ + " is not in valid type or unit");
}
- return (int) (minimalSize / mDisplayMetrics.density);
+ return (int) TypedValue.complexToFloat(value.data);
}
private boolean updateOrientation(boolean forceUpdate) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index 47bdba3..41eb2c9 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -359,12 +359,6 @@
CAMERA_OPENED_ROTATION_UPDATE_DELAY_MS);
}
- private void updateOrientationWithWmLock() {
- synchronized (mWmService.mGlobalLock) {
- mDisplayContent.updateOrientation();
- }
- }
-
private void delayedUpdateOrientationWithWmLock(
@NonNull String cameraId, @NonNull String packageName) {
synchronized (this) {
@@ -375,25 +369,28 @@
}
mCameraIdPackageBiMap.put(packageName, cameraId);
}
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null || topActivity.getTask() == null) {
- return;
- }
- // Checking whether an activity in fullscreen rather than the task as this camera compat
- // treatment doesn't cover activity embedding.
- if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
- if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
- topActivity.recomputeConfiguration();
+ synchronized (mWmService.mGlobalLock) {
+ ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity == null || topActivity.getTask() == null) {
+ return;
}
- updateOrientationWithWmLock();
- return;
- }
- // Checking that the whole app is in multi-window mode as we shouldn't show toast
- // for the activity embedding case.
- if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
- && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
- showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
+ // Checking whether an activity in fullscreen rather than the task as this camera
+ // compat treatment doesn't cover activity embedding.
+ if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ if (topActivity.mLetterboxUiController
+ .isOverrideOrientationOnlyForCameraEnabled()) {
+ topActivity.recomputeConfiguration();
+ }
+ mDisplayContent.updateOrientation();
+ return;
+ }
+ // Checking that the whole app is in multi-window mode as we shouldn't show toast
+ // for the activity embedding case.
+ if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
+ && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
+ showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
+ }
}
}
@@ -441,18 +438,20 @@
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Display id=%d is notified that Camera %s is closed, updating rotation.",
mDisplayContent.mDisplayId, cameraId);
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null
- // Checking whether an activity in fullscreen rather than the task as this camera
- // compat treatment doesn't cover activity embedding.
- || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
- return;
+ synchronized (mWmService.mGlobalLock) {
+ ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity == null
+ // Checking whether an activity in fullscreen rather than the task as this
+ // camera compat treatment doesn't cover activity embedding.
+ || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ return;
+ }
+ if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
+ topActivity.recomputeConfiguration();
+ }
+ mDisplayContent.updateOrientation();
}
- if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
- topActivity.recomputeConfiguration();
- }
- updateOrientationWithWmLock();
}
private boolean isActivityForCameraIdRefreshing(String cameraId) {
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index 594929b..244656c 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -49,7 +49,7 @@
30066 wm_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
# Keyguard status changed
-30067 wm_set_keyguard_shown (Display Id|1|5),(keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(Reason|3)
+30067 wm_set_keyguard_shown (Display Id|1|5),(keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(occluded|1),(Reason|3)
# Out of memory for surfaces.
31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
@@ -65,6 +65,8 @@
# bootanim finished:
31007 wm_boot_animation_done (time|2|3)
+# Notify keyguard occlude statuc change to SysUI.
+31008 wm_set_keyguard_occluded (occluded|1),(animate|1),(transit|1),(Channel|3)
# Back navigation.
31100 wm_back_navi_canceled (Reason|3)
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 25ce569..210a7d9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -344,6 +344,19 @@
}
}
+ if (!attrs.isFullscreen() || attrs.getFitInsetsTypes() != 0) {
+ if (state == originalState) {
+ state = new InsetsState(originalState);
+ }
+ // Explicitly exclude floating windows from receiving caption insets. This is because we
+ // hard code caption insets for windows due to a synchronization issue that leads to
+ // flickering that bypasses insets frame calculation, which consequently needs us to
+ // remove caption insets from floating windows.
+ // TODO(b/254128050): Remove this workaround after we find a way to update window frames
+ // and caption insets frames simultaneously.
+ state.removeSource(InsetsState.ITYPE_CAPTION_BAR);
+ }
+
final SparseArray<WindowContainerInsetsSourceProvider> providers =
mStateController.getSourceProviders();
final int windowType = attrs.type;
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 32b3ccf..08a6358 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -188,6 +188,7 @@
keyguardShowing ? 1 : 0,
aodShowing ? 1 : 0,
state.mKeyguardGoingAway ? 1 : 0,
+ state.mOccluded ? 1 : 0,
"setKeyguardShown");
// Update the task snapshot if the screen will not be turned off. To make sure that the
@@ -253,9 +254,10 @@
try {
EventLogTags.writeWmSetKeyguardShown(
displayId,
- 1 /* keyguardShowing */,
+ state.mKeyguardShowing ? 1 : 0,
state.mAodShowing ? 1 : 0,
1 /* keyguardGoingAway */,
+ state.mOccluded ? 1 : 0,
"keyguardGoingAway");
final int transitFlags = convertTransitFlags(flags);
final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
@@ -669,6 +671,15 @@
boolean hasChange = false;
if (lastOccluded != mOccluded) {
+ if (mDisplayId == DEFAULT_DISPLAY) {
+ EventLogTags.writeWmSetKeyguardShown(
+ mDisplayId,
+ mKeyguardShowing ? 1 : 0,
+ mAodShowing ? 1 : 0,
+ mKeyguardGoingAway ? 1 : 0,
+ mOccluded ? 1 : 0,
+ "updateVisibility");
+ }
controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity);
hasChange = true;
} else if (!lastKeyguardGoingAway && mKeyguardGoingAway) {
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index dc674c2..44b1cc8 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -862,10 +862,9 @@
return mActivityRecord.mWmService.mContext.getResources();
}
- private void handleHorizontalDoubleTap(int x) {
- // TODO(b/260857308): Investigate if enabling reachability for translucent activity
- if (hasInheritedLetterboxBehavior() || !isHorizontalReachabilityEnabled()
- || mActivityRecord.isInTransition()) {
+ @VisibleForTesting
+ void handleHorizontalDoubleTap(int x) {
+ if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
return;
}
@@ -903,10 +902,9 @@
mActivityRecord.recomputeConfiguration();
}
- private void handleVerticalDoubleTap(int y) {
- // TODO(b/260857308): Investigate if enabling reachability for translucent activity
- if (hasInheritedLetterboxBehavior() || !isVerticalReachabilityEnabled()
- || mActivityRecord.isInTransition()) {
+ @VisibleForTesting
+ void handleVerticalDoubleTap(int y) {
+ if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 3635ebb..b879d1a 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
+
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
@@ -195,6 +197,13 @@
+ " transit=%s, apps=%d, wallpapers=%d, nonApps=%d",
AppTransition.appTransitionOldToString(transit), appTargets.length,
wallpaperTargets.length, nonAppTargets.length);
+ if (AppTransition.isKeyguardOccludeTransitOld(transit)) {
+ EventLogTags.writeWmSetKeyguardOccluded(
+ transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE ? 0 : 1,
+ 1 /* animate */,
+ transit,
+ "onAnimationStart");
+ }
mRemoteAnimationAdapter.getRunner().onAnimationStart(transit, appTargets,
wallpaperTargets, nonAppTargets, mFinishedCallback);
} catch (RemoteException e) {
@@ -356,6 +365,11 @@
final boolean isKeyguardOccluded = mDisplayContent.isKeyguardOccluded();
try {
+ EventLogTags.writeWmSetKeyguardOccluded(
+ isKeyguardOccluded ? 1 : 0,
+ 0 /* animate */,
+ 0 /* transit */,
+ "onAnimationCancelled");
mRemoteAnimationAdapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify cancel", e);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0a833f4..7433c7e 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2035,6 +2035,10 @@
Rect outOverrideBounds = getResolvedOverrideConfiguration().windowConfiguration.getBounds();
if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
+ if (!mCreatedByOrganizer) {
+ // Use empty bounds to indicate "fill parent".
+ outOverrideBounds.setEmpty();
+ }
// The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
// the parent or display is smaller than the size, the content may be cropped.
return;
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 3cec3aa..76759ba 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -49,6 +49,7 @@
import android.util.Slog;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
+import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
@@ -1486,7 +1487,7 @@
*/
private boolean isLargeEnoughForMultiWindow() {
return getConfiguration().smallestScreenWidthDp
- >= mAtmService.mLargeScreenSmallestScreenWidthDp;
+ >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
}
boolean isTopRootTask(Task rootTask) {
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 808e79d..035859e 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2574,6 +2574,7 @@
*/
TaskFragmentInfo getTaskFragmentInfo() {
List<IBinder> childActivities = new ArrayList<>();
+ List<IBinder> inRequestedTaskFragmentActivities = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
final WindowContainer<?> wc = getChildAt(i);
final ActivityRecord ar = wc.asActivityRecord();
@@ -2582,6 +2583,9 @@
&& ar.getUid() == mTaskFragmentOrganizerUid && !ar.finishing) {
// Only includes Activities that belong to the organizer process for security.
childActivities.add(ar.token);
+ if (ar.mRequestedLaunchingTaskFragmentToken == mFragmentToken) {
+ inRequestedTaskFragmentActivities.add(ar.token);
+ }
}
}
final Point positionInParent = new Point();
@@ -2593,6 +2597,7 @@
getNonFinishingActivityCount(),
shouldBeVisible(null /* starting */),
childActivities,
+ inRequestedTaskFragmentActivities,
positionInParent,
mClearedTaskForReuse,
mClearedTaskFragmentForPip,
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index bf760c9..5e8b115 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -814,7 +814,7 @@
}
boolean hasParticipatedDisplay = false;
- boolean reportTaskStackChanged = false;
+ boolean hasVisibleTransientLaunch = false;
// Commit all going-invisible containers
for (int i = 0; i < mParticipants.size(); ++i) {
final WindowContainer<?> participant = mParticipants.valueAt(i);
@@ -857,7 +857,7 @@
&& ar.isVisible()) {
// Transient launch was committed, so report enteringAnimation
ar.mEnteringAnimation = true;
- reportTaskStackChanged = true;
+ hasVisibleTransientLaunch = true;
// Since transient launches don't automatically take focus, make sure we
// synchronize focus since we committed to the launch.
@@ -901,8 +901,14 @@
}
}
- if (reportTaskStackChanged) {
+ if (hasVisibleTransientLaunch) {
+ // Notify the change about the transient-below task that becomes invisible.
mController.mAtm.getTaskChangeNotificationController().notifyTaskStackChanged();
+ // Prevent spurious background app switches.
+ mController.mAtm.stopAppSwitches();
+ // The end of transient launch may not reorder task, so make sure to compute the latest
+ // task rank according to the current visibility.
+ mController.mAtm.mRootWindowContainer.rankTaskLayers();
}
// dispatch legacy callback in a different loop. This is because multiple legacy handlers
@@ -984,6 +990,9 @@
cleanUpInternal();
mController.updateAnimatingState(mTmpTransaction);
mTmpTransaction.apply();
+
+ // Handle back animation if it's already started.
+ mController.mAtm.mBackNavigationController.handleDeferredBackAnimation(mTargets);
}
void abort() {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 3464a72..87da85e 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -74,7 +74,9 @@
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.AndroidRuntimeException;
@@ -998,11 +1000,14 @@
activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
}
final Bundle options = activityOptions != null ? activityOptions.toBundle() : null;
- waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
+ int res = waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
hop.getPendingIntent().getTarget(),
hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
null /* requiredPermission */, options));
+ if (ActivityManager.isStartResultSuccessful(res)) {
+ effects |= TRANSACT_EFFECTS_LIFECYCLE;
+ }
break;
}
case HIERARCHY_OP_TYPE_START_SHORTCUT: {
@@ -1353,9 +1358,16 @@
* Post and wait for the result of the activity start to prevent potential deadlock against
* {@link WindowManagerGlobalLock}.
*/
- private void waitAsyncStart(IntSupplier startActivity) {
+ private int waitAsyncStart(IntSupplier startActivity) {
final Integer[] starterResult = {null};
- mService.mH.post(() -> {
+ final Handler handler = (Looper.myLooper() == mService.mH.getLooper())
+ // uncommon case where a queued transaction is trying to start an activity. We can't
+ // post to our own thread and wait (otherwise we deadlock), so use anim thread
+ // instead (which is 1 higher priority).
+ ? mService.mWindowManager.mAnimationHandler
+ // Otherwise just put it on main handler
+ : mService.mH;
+ handler.post(() -> {
try {
starterResult[0] = startActivity.getAsInt();
} catch (Throwable t) {
@@ -1372,6 +1384,7 @@
} catch (InterruptedException ignored) {
}
}
+ return starterResult[0];
}
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 7c0318d..694f1be 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -210,7 +210,7 @@
/** Whether {@link #mLastReportedConfiguration} is deferred by the cached state. */
private volatile boolean mHasCachedConfiguration;
- private int mTopActivityDeviceId = Context.DEVICE_ID_DEFAULT;
+ private int mLastTopActivityDeviceId = Context.DEVICE_ID_DEFAULT;
/**
* Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
* registered.
@@ -1411,8 +1411,9 @@
// If deviceId for the top-activity changed, schedule passing it to the app process.
boolean topActivityDeviceChanged = false;
int deviceId = getTopActivityDeviceId();
- if (deviceId != mTopActivityDeviceId) {
+ if (deviceId != mLastTopActivityDeviceId) {
topActivityDeviceChanged = true;
+ mLastTopActivityDeviceId = deviceId;
}
final Configuration config = getConfiguration();
@@ -1431,15 +1432,12 @@
return;
}
- // TODO(b/263402938): Add tests that capture the deviceId dispatch to the client.
- mTopActivityDeviceId = deviceId;
- dispatchConfiguration(config, topActivityDeviceChanged ? mTopActivityDeviceId
- : Context.DEVICE_ID_INVALID);
+ dispatchConfiguration(config);
}
private int getTopActivityDeviceId() {
ActivityRecord topActivity = getTopNonFinishingActivity();
- int updatedDeviceId = mTopActivityDeviceId;
+ int updatedDeviceId = Context.DEVICE_ID_DEFAULT;
if (topActivity != null && topActivity.mDisplayContent != null) {
updatedDeviceId = mAtm.mTaskSupervisor.getDeviceIdForDisplayId(
topActivity.mDisplayContent.mDisplayId);
@@ -1484,10 +1482,6 @@
}
void dispatchConfiguration(Configuration config) {
- dispatchConfiguration(config, getTopActivityDeviceId());
- }
-
- void dispatchConfiguration(Configuration config, int deviceId) {
mHasPendingConfigurationChange = false;
if (mThread == null) {
if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1514,16 +1508,10 @@
}
}
- scheduleConfigurationChange(mThread, config, deviceId);
+ scheduleConfigurationChange(mThread, config);
}
private void scheduleConfigurationChange(IApplicationThread thread, Configuration config) {
- // By default send invalid deviceId as no-op signal so it's not updated on the client side.
- scheduleConfigurationChange(thread, config, Context.DEVICE_ID_INVALID);
- }
-
- private void scheduleConfigurationChange(IApplicationThread thread, Configuration config,
- int deviceId) {
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
config);
if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1533,7 +1521,7 @@
mHasCachedConfiguration = false;
try {
mAtm.getLifecycleManager().scheduleTransaction(thread,
- ConfigurationChangeItem.obtain(config, deviceId));
+ ConfigurationChangeItem.obtain(config, mLastTopActivityDeviceId));
} catch (Exception e) {
Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change: " + mOwner, e);
}
@@ -1838,6 +1826,9 @@
pw.print("F|");
}
}
+ if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0) {
+ pw.print("VT|");
+ }
final int taskLayer = stateFlags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
if (taskLayer != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
pw.print("taskLayer=" + taskLayer);
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 9260d2b..981844c 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -26,6 +26,10 @@
<xs:element name="displayConfiguration">
<xs:complexType>
<xs:sequence>
+ <xs:element type ="xs:string" name="name">
+ <xs:annotation name="nullable"/>
+ <xs:annotation name="final"/>
+ </xs:element>
<xs:element type="densityMapping" name="densityMapping" minOccurs="0" maxOccurs="1">
<xs:annotation name="nullable"/>
<xs:annotation name="final"/>
@@ -211,6 +215,32 @@
<xs:element type="brightnessThrottlingMap" name="brightnessThrottlingMap" maxOccurs="unbounded">
<xs:annotation name="final"/>
</xs:element>
+ <xs:element type="refreshRateThrottlingMap" name="refreshRateThrottlingMap" maxOccurs="unbounded">
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="refreshRateThrottlingMap">
+ <xs:attribute name="id" type="xs:string" />
+ <xs:sequence>
+ <xs:element name="refreshRateThrottlingPoint" type="refreshRateThrottlingPoint" maxOccurs="unbounded">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="refreshRateThrottlingPoint">
+ <xs:sequence>
+ <xs:element type="thermalStatus" name="thermalStatus">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element type="refreshRateRange" name="refreshRateRange">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index e81c27d..8cb4837 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -89,6 +89,7 @@
method public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholdsIdle();
method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
method public final com.android.server.display.config.SensorDetails getLightSensor();
+ method @Nullable public final String getName();
method public final com.android.server.display.config.SensorDetails getProxSensor();
method public com.android.server.display.config.DisplayQuirks getQuirks();
method public com.android.server.display.config.RefreshRateConfigs getRefreshRate();
@@ -114,6 +115,7 @@
method public final void setDisplayBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds);
method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
method public final void setLightSensor(com.android.server.display.config.SensorDetails);
+ method public final void setName(@Nullable String);
method public final void setProxSensor(com.android.server.display.config.SensorDetails);
method public void setQuirks(com.android.server.display.config.DisplayQuirks);
method public void setRefreshRate(com.android.server.display.config.RefreshRateConfigs);
@@ -214,6 +216,21 @@
method public final void setMinimum(java.math.BigInteger);
}
+ public class RefreshRateThrottlingMap {
+ ctor public RefreshRateThrottlingMap();
+ method public String getId();
+ method @NonNull public final java.util.List<com.android.server.display.config.RefreshRateThrottlingPoint> getRefreshRateThrottlingPoint();
+ method public void setId(String);
+ }
+
+ public class RefreshRateThrottlingPoint {
+ ctor public RefreshRateThrottlingPoint();
+ method @NonNull public final com.android.server.display.config.RefreshRateRange getRefreshRateRange();
+ method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatus();
+ method public final void setRefreshRateRange(@NonNull com.android.server.display.config.RefreshRateRange);
+ method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
+ }
+
public class RefreshRateZone {
ctor public RefreshRateZone();
method public String getId();
@@ -264,6 +281,7 @@
public class ThermalThrottling {
ctor public ThermalThrottling();
method public final java.util.List<com.android.server.display.config.BrightnessThrottlingMap> getBrightnessThrottlingMap();
+ method public final java.util.List<com.android.server.display.config.RefreshRateThrottlingMap> getRefreshRateThrottlingMap();
}
public class ThresholdPoint {
diff --git a/services/core/xsd/display-layout-config/display-layout-config.xsd b/services/core/xsd/display-layout-config/display-layout-config.xsd
index d4556d7..ce022e9 100644
--- a/services/core/xsd/display-layout-config/display-layout-config.xsd
+++ b/services/core/xsd/display-layout-config/display-layout-config.xsd
@@ -52,6 +52,7 @@
<xs:element name="address" type="xs:nonNegativeInteger"/>
<xs:element name="position" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="brightnessThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="refreshRateThermalThrottlingMapId" type="xs:string" minOccurs="0" />
</xs:sequence>
<xs:attribute name="enabled" type="xs:boolean" use="optional" />
<xs:attribute name="defaultDisplay" type="xs:boolean" use="optional" />
diff --git a/services/core/xsd/display-layout-config/schema/current.txt b/services/core/xsd/display-layout-config/schema/current.txt
index 52133ab..42a800d 100644
--- a/services/core/xsd/display-layout-config/schema/current.txt
+++ b/services/core/xsd/display-layout-config/schema/current.txt
@@ -7,6 +7,7 @@
method public String getBrightnessThrottlingMapId();
method public String getDisplayGroup();
method public String getPosition();
+ method public String getRefreshRateThermalThrottlingMapId();
method public String getRefreshRateZoneId();
method public boolean isDefaultDisplay();
method public boolean isEnabled();
@@ -16,6 +17,7 @@
method public void setDisplayGroup(String);
method public void setEnabled(boolean);
method public void setPosition(String);
+ method public void setRefreshRateThermalThrottlingMapId(String);
method public void setRefreshRateZoneId(String);
}
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index f8b1e6fc..6bf18c2 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -29,6 +29,9 @@
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
import java.util.ArrayList;
/**
@@ -119,18 +122,21 @@
// TODO: Differentiate btw cancelled and false
mChosenProviderMetric.setChosenProviderStatus(
MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_SUCCESS);
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
try {
mClientCallback.onSuccess();
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_SUCCESS);
} catch (RemoteException e) {
mChosenProviderMetric.setChosenProviderStatus(
MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_FAILURE);
Log.i(TAG, "Issue while propagating the response to the client");
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
}
finishSession(/*propagateCancellation=*/false);
}
@@ -139,7 +145,8 @@
Log.i(TAG, "respondToClientWithErrorAndFinish");
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
@@ -148,7 +155,8 @@
} catch (RemoteException e) {
e.printStackTrace();
}
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
finishSession(/*propagateCancellation=*/false);
}
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 4dd0c84..656e44c 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -36,6 +36,9 @@
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
import java.util.ArrayList;
/**
@@ -141,16 +144,19 @@
}
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
try {
mClientCallback.onResponse(response);
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_SUCCESS);
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client: " + e.getMessage());
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
}
finishSession(/*propagateCancellation=*/false);
}
@@ -163,7 +169,8 @@
}
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
@@ -172,10 +179,20 @@
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client: " + e.getMessage());
}
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+ logFailureOrUserCancel(errorType);
finishSession(/*propagateCancellation=*/false);
}
+ private void logFailureOrUserCancel(String errorType) {
+ if (CreateCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+ logApiCall(ApiName.CREATE_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_USER_CANCELED);
+ } else {
+ logApiCall(ApiName.CREATE_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_FAILURE);
+ }
+ }
+
@Override
public void onProviderStatusChanged(ProviderSession.Status status,
ComponentName componentName) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
index 9c50a5a..d768d23 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
@@ -23,6 +23,8 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.HashMap;
import java.util.HashSet;
@@ -90,6 +92,18 @@
}
}
+ /** Clears an existing session for a given user identifier. */
+ @GuardedBy("sLock")
+ @VisibleForTesting
+ public static void clearAllSessions() {
+ sLock.lock();
+ try {
+ sCredentialDescriptionSessionPerUser.clear();
+ } finally {
+ sLock.unlock();
+ }
+ }
+
private Map<String, Set<CredentialDescription>> mCredentialDescriptions;
private int mTotalDescriptionCount;
@@ -138,6 +152,9 @@
public Set<FilterResult> getFilteredResultForProvider(String packageName,
String flatRequestStrings) {
Set<FilterResult> result = new HashSet<>();
+ if (!mCredentialDescriptions.containsKey(packageName)) {
+ return result;
+ }
Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
for (CredentialDescription containedDescription: currentSet) {
if (flatRequestStrings.equals(containedDescription.getFlattenedRequestString())) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 7a4e7df..41ae911 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -64,6 +64,8 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.SecureSettingsServiceNameResolver;
@@ -84,7 +86,7 @@
*/
public final class CredentialManagerService
extends AbstractMasterSystemService<
- CredentialManagerService, CredentialManagerServiceImpl> {
+ CredentialManagerService, CredentialManagerServiceImpl> {
private static final String TAG = "CredManSysService";
private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
@@ -267,7 +269,8 @@
final long origId = Binder.clearCallingIdentity();
try {
return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
+ DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API,
+ false);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -317,8 +320,8 @@
Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>> result =
new HashSet<>();
- for (CredentialDescriptionRegistry.FilterResult filterResult: filterResults) {
- for (CredentialOption credentialOption: options) {
+ for (CredentialDescriptionRegistry.FilterResult filterResult : filterResults) {
+ for (CredentialOption credentialOption : options) {
if (filterResult.mFlattenedRequest.equals(credentialOption
.getCredentialRetrievalData()
.getString(CredentialOption.FLATTENED_REQUEST))) {
@@ -364,13 +367,13 @@
CallingAppInfo callingAppInfo;
try {
packageInfo =
- getContext()
- .getPackageManager()
- .getPackageInfoAsUser(
- realPackageName,
- PackageManager.PackageInfoFlags.of(
- PackageManager.GET_SIGNING_CERTIFICATES),
- userId);
+ getContext()
+ .getPackageManager()
+ .getPackageInfoAsUser(
+ realPackageName,
+ PackageManager.PackageInfoFlags.of(
+ PackageManager.GET_SIGNING_CERTIFICATES),
+ userId);
callingAppInfo = new CallingAppInfo(realPackageName, packageInfo.signingInfo, origin);
} catch (PackageManager.NameNotFoundException e) {
Log.i(TAG, "Issue while retrieving signatureInfo : " + e.getMessage());
@@ -421,41 +424,41 @@
if (isCredentialDescriptionApiEnabled()) {
List<CredentialOption> optionsThatRequireActiveCredentials =
request.getCredentialOptions().stream()
- .filter(
- getCredentialOption ->
- !TextUtils.isEmpty(
- getCredentialOption
- .getCredentialRetrievalData()
- .getString(
- CredentialOption
- .FLATTENED_REQUEST,
- null)))
- .toList();
+ .filter(
+ getCredentialOption ->
+ !TextUtils.isEmpty(
+ getCredentialOption
+ .getCredentialRetrievalData()
+ .getString(
+ CredentialOption
+ .FLATTENED_REQUEST,
+ null)))
+ .toList();
List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
request.getCredentialOptions().stream()
- .filter(
- getCredentialOption ->
- TextUtils.isEmpty(
- getCredentialOption
- .getCredentialRetrievalData()
- .getString(
- CredentialOption
- .FLATTENED_REQUEST,
- null)))
- .toList();
+ .filter(
+ getCredentialOption ->
+ TextUtils.isEmpty(
+ getCredentialOption
+ .getCredentialRetrievalData()
+ .getString(
+ CredentialOption
+ .FLATTENED_REQUEST,
+ null)))
+ .toList();
List<ProviderSession> sessionsWithoutRemoteService =
initiateProviderSessionsWithActiveContainers(
- session,
- getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
+ session,
+ getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
List<ProviderSession> sessionsWithRemoteService =
initiateProviderSessions(
- session,
- optionsThatDoNotRequireActiveCredentials.stream()
- .map(CredentialOption::getType)
- .collect(Collectors.toList()));
+ session,
+ optionsThatDoNotRequireActiveCredentials.stream()
+ .map(CredentialOption::getType)
+ .collect(Collectors.toList()));
Set<ProviderSession> all = new LinkedHashSet<>();
all.addAll(sessionsWithRemoteService);
@@ -465,11 +468,11 @@
} else {
// Initiate all provider sessions
providerSessions =
- initiateProviderSessions(
- session,
- request.getCredentialOptions().stream()
- .map(CredentialOption::getType)
- .collect(Collectors.toList()));
+ initiateProviderSessions(
+ session,
+ request.getCredentialOptions().stream()
+ .map(CredentialOption::getType)
+ .collect(Collectors.toList()));
}
if (providerSessions.isEmpty()) {
@@ -481,8 +484,8 @@
Log.i(
TAG,
"Issue invoking onError on IGetCredentialCallback "
- + "callback: "
- + e.getMessage());
+ + "callback: "
+ + e.getMessage());
}
}
providerSessions.forEach(ProviderSession::invokeSession);
@@ -538,8 +541,8 @@
Log.i(
TAG,
"Issue invoking onError on ICreateCredentialCallback "
- + "callback: "
- + e.getMessage());
+ + "callback: "
+ + e.getMessage());
}
}
@@ -654,13 +657,17 @@
if (serviceComponentName.equals(componentName)) {
if (!s.getServicePackageName().equals(callingPackage)) {
// The component name and the package name do not match.
+ MetricUtilities.logApiCalled(
+ ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+ ApiStatus.METRICS_API_STATUS_FAILURE, callingUid);
Log.w(
TAG,
"isEnabledCredentialProviderService: Component name does not"
+ " match package name.");
return false;
}
-
+ MetricUtilities.logApiCalled(ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+ ApiStatus.METRICS_API_STATUS_SUCCESS, callingUid);
return true;
}
}
@@ -745,7 +752,7 @@
enforceCallingPackage(callingPackage, Binder.getCallingUid());
List<CredentialProviderInfo> services =
- getServicesForCredentialDescription(UserHandle.getCallingUserId());
+ getServicesForCredentialDescription(UserHandle.getCallingUserId());
List<String> providers =
services.stream()
@@ -801,7 +808,7 @@
enforceCallingPackage(callingPackage, Binder.getCallingUid());
List<CredentialProviderInfo> services =
- getServicesForCredentialDescription(UserHandle.getCallingUserId());
+ getServicesForCredentialDescription(UserHandle.getCallingUserId());
List<String> providers =
services.stream()
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 32b14d7..ce26c88 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -34,6 +34,9 @@
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
import java.util.ArrayList;
/**
@@ -117,16 +120,19 @@
}
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
try {
mClientCallback.onResponse(response);
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_SUCCESS);
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
}
finishSession(/*propagateCancellation=*/false);
}
@@ -137,7 +143,8 @@
return;
}
if (isSessionCancelled()) {
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
@@ -147,10 +154,20 @@
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());
}
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logFailureOrUserCancel(errorType);
finishSession(/*propagateCancellation=*/false);
}
+ private void logFailureOrUserCancel(String errorType) {
+ if (GetCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+ logApiCall(ApiName.GET_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_USER_CANCELED);
+ } else {
+ logApiCall(ApiName.GET_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_FAILURE);
+ }
+ }
+
@Override
public void onUiCancellation(boolean isUserCancellation) {
if (isUserCancellation) {
diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
index 27d9836d..f75a9b6 100644
--- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java
+++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
@@ -16,14 +16,6 @@
package com.android.server.credentials;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_SUCCESS;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_FAILURE;
@@ -35,6 +27,14 @@
import android.content.pm.PackageManager;
import android.util.Log;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.CandidateProviderMetric;
+import com.android.server.credentials.metrics.ChosenProviderMetric;
+
+import java.util.Map;
+
/**
* For all future metric additions, this will contain their names for local usage after importing
* from {@link com.android.internal.util.FrameworkStatsLog}.
@@ -43,24 +43,10 @@
private static final String TAG = "MetricUtilities";
- // Metrics constants
- protected static final int METRICS_API_NAME_UNKNOWN =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
- protected static final int METRICS_API_NAME_GET_CREDENTIAL =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
- protected static final int METRICS_API_NAME_CREATE_CREDENTIAL =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
- protected static final int METRICS_API_NAME_CLEAR_CREDENTIAL =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
- // TODO add isEnabled
- protected static final int METRICS_API_STATUS_SUCCESS =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
- protected static final int METRICS_API_STATUS_FAILURE =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
- protected static final int METRICS_API_STATUS_CLIENT_CANCEL =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
- protected static final int METRICS_API_STATUS_USER_CANCEL =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
+ private static final int DEFAULT_INT_32 = -1;
+ private static final int[] DEFAULT_REPEATED_INT_32 = new int[0];
+
+ // Metrics constants TODO(b/269290341) migrate to enums eventually to improve
protected static final int METRICS_PROVIDER_STATUS_FINAL_FAILURE =
CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
protected static final int METRICS_PROVIDER_STATUS_QUERY_FAILURE =
@@ -77,6 +63,7 @@
* This retrieves the uid of any package name, given a context and a component name for the
* package. By default, if the desired package uid cannot be found, it will fall back to a
* bogus uid.
+ *
* @return the uid of a given package
*/
protected static int getPackageUid(Context context, ComponentName componentName) {
@@ -92,4 +79,75 @@
return sessUid;
}
+ /**
+ * The most common logging helper, handles the overall status of the API request with the
+ * provider status and latencies. Other versions of this method may be more useful depending
+ * on the situation, as this is geared towards the logging of {@link ProviderSession} types.
+ *
+ * @param apiName the api type to log
+ * @param apiStatus the api status to log
+ * @param providers a map with known providers
+ * @param callingUid the calling UID of the client app
+ * @param chosenProviderMetric the metric data type of the final chosen provider
+ */
+ protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+ Map<String, ProviderSession> providers, int callingUid,
+ ChosenProviderMetric chosenProviderMetric) {
+ var providerSessions = providers.values();
+ int providerSize = providerSessions.size();
+ int[] candidateUidList = new int[providerSize];
+ int[] candidateQueryRoundTripTimeList = new int[providerSize];
+ int[] candidateStatusList = new int[providerSize];
+ int index = 0;
+ for (var session : providerSessions) {
+ CandidateProviderMetric metric = session.mCandidateProviderMetric;
+ candidateUidList[index] = metric.getCandidateUid();
+ candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMs();
+ candidateStatusList[index] = metric.getProviderQueryStatus();
+ index++;
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+ /* api_name */apiName.getMetricCode(),
+ /* caller_uid */ callingUid,
+ /* api_status */ apiStatus.getMetricCode(),
+ /* repeated_candidate_provider_uid */ candidateUidList,
+ /* repeated_candidate_provider_round_trip_time_query_microseconds */
+ candidateQueryRoundTripTimeList,
+ /* repeated_candidate_provider_status */ candidateStatusList,
+ /* chosen_provider_uid */ chosenProviderMetric.getChosenUid(),
+ /* chosen_provider_round_trip_time_overall_microseconds */
+ chosenProviderMetric.getEntireProviderLatencyMs(),
+ /* chosen_provider_final_phase_microseconds */
+ chosenProviderMetric.getFinalPhaseLatencyMs(),
+ /* chosen_provider_status */ chosenProviderMetric.getChosenProviderStatus());
+ }
+
+ /**
+ * This is useful just to record an API calls' final event, and for no other purpose. It will
+ * contain default values for all other optional parameters.
+ *
+ * TODO(b/271135048) - given space requirements, this may be a good candidate for another atom
+ *
+ * @param apiName the api name to log
+ * @param apiStatus the status to log
+ * @param callingUid the calling uid
+ */
+ protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+ int callingUid) {
+ FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+ /* api_name */apiName.getMetricCode(),
+ /* caller_uid */ callingUid,
+ /* api_status */ apiStatus.getMetricCode(),
+ /* repeated_candidate_provider_uid */ DEFAULT_REPEATED_INT_32,
+ /* repeated_candidate_provider_round_trip_time_query_microseconds */
+ DEFAULT_REPEATED_INT_32,
+ /* repeated_candidate_provider_status */ DEFAULT_REPEATED_INT_32,
+ /* chosen_provider_uid */ DEFAULT_INT_32,
+ /* chosen_provider_round_trip_time_overall_microseconds */
+ DEFAULT_INT_32,
+ /* chosen_provider_final_phase_microseconds */
+ DEFAULT_INT_32,
+ /* chosen_provider_status */ DEFAULT_INT_32);
+ }
+
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 3245c91..97b7811 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -35,6 +35,7 @@
import android.service.credentials.CreateEntry;
import android.service.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderService;
+import android.service.credentials.RemoteEntry;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -301,14 +302,14 @@
@NonNull
private final Map<String, Pair<CreateEntry, Entry>> mUiCreateEntries = new HashMap<>();
- @Nullable private Pair<String, Pair<CreateEntry, Entry>> mUiRemoteEntry = null;
+ @Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(String hybridService) {
mExpectedRemoteEntryProviderService = ComponentName.unflattenFromString(hybridService);
}
public void addResponseContent(List<CreateEntry> createEntries,
- CreateEntry remoteEntry) {
+ RemoteEntry remoteEntry) {
createEntries.forEach(this::addCreateEntry);
setRemoteEntry(remoteEntry);
}
@@ -319,7 +320,7 @@
mUiCreateEntries.put(id, new Pair<>(createEntry, entry));
}
- public void setRemoteEntry(@Nullable CreateEntry remoteEntry) {
+ public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
if (remoteEntry == null) {
mUiRemoteEntry = null;
return;
@@ -363,7 +364,7 @@
return mUiCreateEntries.isEmpty() && mUiRemoteEntry == null;
}
@Nullable
- public CreateEntry getRemoteEntry(String entryKey) {
+ public RemoteEntry getRemoteEntry(String entryKey) {
return mUiRemoteEntry == null || mUiRemoteEntry
.first == null || !mUiRemoteEntry.first.equals(entryKey)
|| mUiRemoteEntry.second == null
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 6498b6a..ee813e9 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -38,6 +38,7 @@
import android.service.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderService;
import android.service.credentials.GetCredentialRequest;
+import android.service.credentials.RemoteEntry;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -299,7 +300,7 @@
}
return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
new GetCredentialRequest(
- mCallingAppInfo, mBeginGetOptionToCredentialOptionMap.get(id)));
+ mCallingAppInfo, List.of(mBeginGetOptionToCredentialOptionMap.get(id))));
}
private Intent setUpFillInIntentWithQueryRequest() {
@@ -472,7 +473,7 @@
private final Map<String, Pair<Action, AuthenticationEntry>> mUiAuthenticationEntries =
new HashMap<>();
- @Nullable private Pair<String, Pair<CredentialEntry, Entry>> mUiRemoteEntry = null;
+ @Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(ComponentName expectedRemoteEntryProviderService) {
mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
@@ -480,7 +481,7 @@
public void addResponseContent(List<CredentialEntry> credentialEntries,
List<Action> actions, List<Action> authenticationActions,
- CredentialEntry remoteEntry) {
+ RemoteEntry remoteEntry) {
credentialEntries.forEach(this::addCredentialEntry);
actions.forEach(this::addAction);
authenticationActions.forEach(
@@ -522,7 +523,7 @@
mUiAuthenticationEntries.remove(id);
}
- public void setRemoteEntry(@Nullable CredentialEntry remoteEntry) {
+ public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
if (remoteEntry == null) {
return;
}
@@ -533,8 +534,7 @@
}
String id = generateUniqueId();
Entry entry = new Entry(REMOTE_ENTRY_KEY,
- id, remoteEntry.getSlice(), setUpFillInIntent(
- remoteEntry.getBeginGetCredentialOption().getId()));
+ id, remoteEntry.getSlice(), setUpFillInIntentForRemoteEntry());
mUiRemoteEntry = new Pair<>(generateUniqueId(), new Pair<>(remoteEntry, entry));
}
@@ -604,7 +604,7 @@
}
@Nullable
- public CredentialEntry getRemoteEntry(String entryKey) {
+ public RemoteEntry getRemoteEntry(String entryKey) {
return mUiRemoteEntry.first.equals(entryKey) && mUiRemoteEntry.second != null
? mUiRemoteEntry.second.first : null;
}
@@ -662,4 +662,10 @@
from.getFrameworkExtrasIntent());
}
}
+
+ private Intent setUpFillInIntentForRemoteEntry() {
+ return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
+ new GetCredentialRequest(
+ mCallingAppInfo, mCompleteRequest.getCredentialOptions()));
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
index a57cb5f..36d6b3d 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
@@ -121,7 +121,7 @@
CredentialProviderService
.EXTRA_GET_CREDENTIAL_REQUEST,
new android.service.credentials.GetCredentialRequest(
- mCallingAppInfo, mProviderRequest));
+ mCallingAppInfo, List.of(mProviderRequest)));
return intent;
}
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index f8bbfcf..86e05cf 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -16,12 +16,7 @@
package com.android.server.credentials;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CLEAR_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CREATE_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_GET_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_UNKNOWN;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_FAILURE;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_SUCCESS;
+import static com.android.server.credentials.MetricUtilities.logApiCalled;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
@@ -39,7 +34,8 @@
import android.util.Log;
import com.android.internal.R;
-import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
import com.android.server.credentials.metrics.CandidateProviderMetric;
import com.android.server.credentials.metrics.ChosenProviderMetric;
@@ -162,50 +158,10 @@
}
return false;
}
- // TODO: move these definitions to a separate logging focused class.
- enum RequestType {
- GET_CREDENTIALS,
- CREATE_CREDENTIALS,
- CLEAR_CREDENTIALS,
- }
- private static int getApiNameFromRequestType(RequestType requestType) {
- switch (requestType) {
- case GET_CREDENTIALS:
- return METRICS_API_NAME_GET_CREDENTIAL;
- case CREATE_CREDENTIALS:
- return METRICS_API_NAME_CREATE_CREDENTIAL;
- case CLEAR_CREDENTIALS:
- return METRICS_API_NAME_CLEAR_CREDENTIAL;
- default:
- return METRICS_API_NAME_UNKNOWN;
- }
- }
-
- protected void logApiCalled(RequestType requestType, boolean isSuccessfulOverall) {
- var providerSessions = mProviders.values();
- int providerSize = providerSessions.size();
- int[] candidateUidList = new int[providerSize];
- int[] candidateQueryRoundTripTimeList = new int[providerSize];
- int[] candidateStatusList = new int[providerSize];
- int index = 0;
- for (var session : providerSessions) {
- CandidateProviderMetric metric = session.mCandidateProviderMetric;
- candidateUidList[index] = metric.getCandidateUid();
- candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMs();
- candidateStatusList[index] = metric.getProviderQueryStatus();
- index++;
- }
- FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
- /* api_name */getApiNameFromRequestType(requestType), /* caller_uid */
- mCallingUid, /* api_status */
- isSuccessfulOverall ? METRICS_API_STATUS_SUCCESS : METRICS_API_STATUS_FAILURE,
- candidateUidList,
- candidateQueryRoundTripTimeList,
- candidateStatusList, mChosenProviderMetric.getChosenUid(),
- mChosenProviderMetric.getEntireProviderLatencyMs(),
- mChosenProviderMetric.getFinalPhaseLatencyMs(),
- mChosenProviderMetric.getChosenProviderStatus());
+ protected void logApiCall(ApiName apiName, ApiStatus apiStatus) {
+ logApiCalled(apiName, apiStatus, mProviders, mCallingUid,
+ mChosenProviderMetric);
}
protected boolean isSessionCancelled() {
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiName.java b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
new file mode 100644
index 0000000..d4b51df
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
+
+public enum ApiName {
+ UNKNOWN(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN),
+ GET_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL),
+ CREATE_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL),
+ CLEAR_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL),
+ IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE(
+ CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE
+ );
+
+ private final int mInnerMetricCode;
+
+ ApiName(int innerMetricCode) {
+ this.mInnerMetricCode = innerMetricCode;
+ }
+
+ /**
+ * Gives the West-world version of the metric name.
+ *
+ * @return a code corresponding to the west world metric name
+ */
+ public int getMetricCode() {
+ return this.mInnerMetricCode;
+ }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
new file mode 100644
index 0000000..36a1f2d
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 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.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
+
+public enum ApiStatus {
+ METRICS_API_STATUS_SUCCESS(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS),
+ METRICS_API_STATUS_FAILURE(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE),
+ METRICS_API_STATUS_CLIENT_CANCELED(
+ CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED),
+ METRICS_API_STATUS_USER_CANCELED(
+ CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED);
+
+ private final int mInnerMetricCode;
+
+ ApiStatus(int innerMetricCode) {
+ this.mInnerMetricCode = innerMetricCode;
+ }
+
+ /**
+ * Gives the West-world version of the metric name.
+ *
+ * @return a code corresponding to the west world metric name
+ */
+ public int getMetricCode() {
+ return this.mInnerMetricCode;
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index bfcb4c7..e9c23a0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11337,7 +11337,7 @@
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_APPLICATION_RESTRICTIONS)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate(caller))
.setStrings(packageName)
.write();
}
@@ -13378,7 +13378,7 @@
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_APPLICATION_HIDDEN)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate(caller))
.setStrings(packageName, hidden ? "hidden" : "not_hidden",
parent ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT)
.write();
@@ -13730,7 +13730,7 @@
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_UNINSTALL_BLOCKED)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate(caller))
.setStrings(packageName)
.write();
}
@@ -16280,7 +16280,8 @@
.setAdmin(caller.getPackageName())
.setStrings(permission)
.setInt(grantState)
- .setBoolean(/* isDelegate */ admin == null)
+ .setBoolean(
+ /* isDelegate */ isCallerDelegate(caller))
.write();
callback.sendResult(Bundle.EMPTY);
@@ -16405,12 +16406,12 @@
mInjector.getPackageManager().getPackagesForUid(caller.getUid()));
Preconditions.checkArgument(callerUidPackageNames.contains(packageName),
"Caller uid doesn't match the one for the provided package.");
+
+ return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId())
+ == STATUS_OK;
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
-
- return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId())
- == STATUS_OK;
}
@Override
@@ -22183,6 +22184,10 @@
private static final HashMap<String, String> DELEGATE_SCOPES = new HashMap<>();
{
DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, DELEGATION_PERMISSION_GRANT);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_APP_RESTRICTIONS, DELEGATION_APP_RESTRICTIONS);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_APPS_CONTROL, DELEGATION_BLOCK_UNINSTALL);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, DELEGATION_SECURITY_LOGGING);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_PACKAGE_STATE, DELEGATION_PACKAGE_ACCESS);
}
private static final HashMap<String, String> CROSS_USER_PERMISSIONS =
@@ -22371,6 +22376,7 @@
+ permission
+ ", "
+ CROSS_USER_PERMISSIONS.get(permission)
+ + "(if calling cross-user)"
+ "}");
}
}
diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING
index 3976a70..be7feb5 100644
--- a/services/incremental/TEST_MAPPING
+++ b/services/incremental/TEST_MAPPING
@@ -16,13 +16,13 @@
},
{
"name": "service.incremental_test"
+ },
+ {
+ "name": "CtsInstalledLoadingProgressHostTests"
}
],
"presubmit-large": [
{
- "name": "CtsInstalledLoadingProgressHostTests"
- },
- {
"name": "CtsContentTestCases",
"options": [
{
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 17e1744..0ca4dfc 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -113,7 +113,6 @@
private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
@VisibleForTesting
static final int MAX_CACHED_RECENT_SHORTCUTS = 30;
- private static final int DEBOUNCE_LENGTH_MS = 500;
private final Context mContext;
private final Injector mInjector;
@@ -130,7 +129,6 @@
private final List<PeopleService.ConversationsListener> mConversationsListeners =
new ArrayList<>(1);
private final Handler mHandler;
- private final PerPackageThrottler mShortcutsThrottler;
private ContentObserver mCallLogContentObserver;
private ContentObserver mMmsSmsContentObserver;
@@ -142,17 +140,14 @@
private ConversationStatusExpirationBroadcastReceiver mStatusExpReceiver;
public DataManager(Context context) {
- this(context, new Injector(), BackgroundThread.get().getLooper(),
- new PerPackageThrottlerImpl(BackgroundThread.getHandler(), DEBOUNCE_LENGTH_MS));
+ this(context, new Injector(), BackgroundThread.get().getLooper());
}
- DataManager(Context context, Injector injector, Looper looper,
- PerPackageThrottler shortcutsThrottler) {
+ DataManager(Context context, Injector injector, Looper looper) {
mContext = context;
mInjector = injector;
mScheduledExecutor = mInjector.createScheduledExecutor();
mHandler = new Handler(looper);
- mShortcutsThrottler = shortcutsThrottler;
}
/** Initialization. Called when the system services are up running. */
@@ -856,12 +851,12 @@
// pair of <package name, conversation info>
List<Pair<String, ConversationInfo>> cachedConvos = new ArrayList<>();
userData.forAllPackages(packageData -> {
- packageData.forAllConversations(conversationInfo -> {
- if (isEligibleForCleanUp(conversationInfo)) {
- cachedConvos.add(
- Pair.create(packageData.getPackageName(), conversationInfo));
- }
- });
+ packageData.forAllConversations(conversationInfo -> {
+ if (isEligibleForCleanUp(conversationInfo)) {
+ cachedConvos.add(
+ Pair.create(packageData.getPackageName(), conversationInfo));
+ }
+ });
});
if (cachedConvos.size() <= targetCachedCount) {
return;
@@ -872,8 +867,8 @@
numToUncache + 1,
Comparator.comparingLong((Pair<String, ConversationInfo> pair) ->
Math.max(
- pair.second.getLastEventTimestamp(),
- pair.second.getCreationTimestamp())).reversed());
+ pair.second.getLastEventTimestamp(),
+ pair.second.getCreationTimestamp())).reversed());
for (Pair<String, ConversationInfo> cached : cachedConvos) {
if (hasActiveNotifications(cached.first, userId, cached.second.getShortcutId())) {
continue;
@@ -1109,35 +1104,26 @@
@Override
public void onShortcutsAddedOrUpdated(@NonNull String packageName,
@NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
- mShortcutsThrottler.scheduleDebounced(
- new Pair<>(packageName, user.getIdentifier()),
- () -> {
- PackageData packageData = getPackage(packageName, user.getIdentifier());
- List<ShortcutInfo> queriedShortcuts = getShortcuts(packageName,
- user.getIdentifier(), null);
- boolean hasCachedShortcut = false;
- for (ShortcutInfo shortcut : queriedShortcuts) {
- if (ShortcutHelper.isConversationShortcut(
- shortcut, mShortcutServiceInternal, user.getIdentifier())) {
- if (shortcut.isCached()) {
- ConversationInfo info = packageData != null
- ? packageData.getConversationInfo(shortcut.getId())
- : null;
- if (info == null
- || !info.isShortcutCachedForNotification()) {
- hasCachedShortcut = true;
- }
- }
- addOrUpdateConversationInfo(shortcut);
+ mInjector.getBackgroundExecutor().execute(() -> {
+ PackageData packageData = getPackage(packageName, user.getIdentifier());
+ for (ShortcutInfo shortcut : shortcuts) {
+ if (ShortcutHelper.isConversationShortcut(
+ shortcut, mShortcutServiceInternal, user.getIdentifier())) {
+ if (shortcut.isCached()) {
+ ConversationInfo conversationInfo = packageData != null
+ ? packageData.getConversationInfo(shortcut.getId()) : null;
+ if (conversationInfo == null
+ || !conversationInfo.isShortcutCachedForNotification()) {
+ // This is a newly cached shortcut. Clean up the existing cached
+ // shortcuts to ensure the cache size is under the limit.
+ cleanupCachedShortcuts(user.getIdentifier(),
+ MAX_CACHED_RECENT_SHORTCUTS - 1);
}
}
- // Added at least one new conversation. Uncache older existing cached
- // shortcuts to ensure the cache size is under the limit.
- if (hasCachedShortcut) {
- cleanupCachedShortcuts(user.getIdentifier(),
- MAX_CACHED_RECENT_SHORTCUTS);
- }
- });
+ addOrUpdateConversationInfo(shortcut);
+ }
+ }
+ });
}
@Override
diff --git a/services/people/java/com/android/server/people/data/PerPackageThrottler.java b/services/people/java/com/android/server/people/data/PerPackageThrottler.java
deleted file mode 100644
index 3d6cd84..0000000
--- a/services/people/java/com/android/server/people/data/PerPackageThrottler.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2023 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.people.data;
-
-import android.util.Pair;
-
-/** The interface for throttling expensive runnables per package. */
-interface PerPackageThrottler {
- /**
- * Schedule a runnable to run in the future, and debounce runnables for same {@code pkgUserId}
- * that occur until that future has run.
- */
- void scheduleDebounced(Pair<String, Integer> pkgUserId, Runnable runnable);
-}
diff --git a/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java b/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java
deleted file mode 100644
index fa5a67b..0000000
--- a/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2023 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.people.data;
-
-import android.os.Handler;
-import android.util.Pair;
-
-import java.util.HashSet;
-
-/**
- * A class that implements a per-package throttler that prevents a runnable from executing more than
- * once every {@code debounceTime}.
- */
-public class PerPackageThrottlerImpl implements PerPackageThrottler {
- private final Handler mBackgroundHandler;
- private final int mDebounceTime;
- private final HashSet<Pair<String, Integer>> mPkgScheduledTasks = new HashSet<>();
-
- PerPackageThrottlerImpl(Handler backgroundHandler, int debounceTime) {
- mBackgroundHandler = backgroundHandler;
- mDebounceTime = debounceTime;
- }
-
- @Override
- public synchronized void scheduleDebounced(
- Pair<String, Integer> pkgUserId, Runnable runnable) {
- if (mPkgScheduledTasks.contains(pkgUserId)) {
- return;
- }
- mPkgScheduledTasks.add(pkgUserId);
- mBackgroundHandler.postDelayed(() -> {
- synchronized (this) {
- mPkgScheduledTasks.remove(pkgUserId);
- runnable.run();
- }
- }, mDebounceTime);
- }
-}
diff --git a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
index 61574d4..f453e79 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
@@ -21,9 +21,9 @@
import com.android.modules.utils.BinaryXmlSerializer
import com.android.server.SystemConfig
import com.android.server.permission.access.appop.PackageAppOpPolicy
-import com.android.server.permission.access.appop.UidAppOpPolicy
+import com.android.server.permission.access.appop.AppIdAppOpPolicy
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.permission.UidPermissionPolicy
+import com.android.server.permission.access.permission.AppIdPermissionPolicy
import com.android.server.permission.access.util.forEachTag
import com.android.server.permission.access.util.tag
import com.android.server.permission.access.util.tagName
@@ -37,8 +37,8 @@
IndexedMap<String, IndexedMap<String, SchemePolicy>>().apply {
fun addPolicy(policy: SchemePolicy) =
getOrPut(policy.subjectScheme) { IndexedMap() }.put(policy.objectScheme, policy)
- addPolicy(UidPermissionPolicy())
- addPolicy(UidAppOpPolicy())
+ addPolicy(AppIdPermissionPolicy())
+ addPolicy(AppIdAppOpPolicy())
addPolicy(PackageAppOpPolicy())
}
)
diff --git a/services/permission/java/com/android/server/permission/access/AccessState.kt b/services/permission/java/com/android/server/permission/access/AccessState.kt
index 5532311..0b4d6e9 100644
--- a/services/permission/java/com/android/server/permission/access/AccessState.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessState.kt
@@ -98,9 +98,9 @@
class UserState private constructor(
// A map of (appId to a map of (permissionName to permissionFlags))
- val uidPermissionFlags: IntMap<IndexedMap<String, Int>>,
+ val appIdPermissionFlags: IntMap<IndexedMap<String, Int>>,
// appId -> opName -> opCode
- val uidAppOpModes: IntMap<IndexedMap<String, Int>>,
+ val appIdAppOpModes: IntMap<IndexedMap<String, Int>>,
// packageName -> opName -> opCode
val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>>
) : WritableState() {
@@ -111,8 +111,8 @@
)
fun copy(): UserState = UserState(
- uidPermissionFlags.copy { it.copy { it } },
- uidAppOpModes.copy { it.copy { it } },
+ appIdPermissionFlags.copy { it.copy { it } },
+ appIdAppOpModes.copy { it.copy { it } },
packageAppOpModes.copy { it.copy { it } }
)
}
diff --git a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
similarity index 79%
rename from services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt
rename to services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
index 7a965d4..c29f30c8 100644
--- a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
@@ -28,15 +28,15 @@
import com.android.server.permission.access.util.tag
import com.android.server.permission.access.util.tagName
-class UidAppOpPersistence : BaseAppOpPersistence() {
+class AppIdAppOpPersistence : BaseAppOpPersistence() {
override fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
when (tagName) {
- TAG_UID_APP_OPS -> parseUidAppOps(state, userId)
+ TAG_APP_ID_APP_OPS -> parseAppIdAppOps(state, userId)
else -> {}
}
}
- private fun BinaryXmlPullParser.parseUidAppOps(state: AccessState, userId: Int) {
+ private fun BinaryXmlPullParser.parseAppIdAppOps(state: AccessState, userId: Int) {
val userState = state.userStates[userId]
forEachTag {
when (tagName) {
@@ -44,7 +44,7 @@
else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
}
}
- userState.uidAppOpModes.retainAllIndexed { _, appId, _ ->
+ userState.appIdAppOpModes.retainAllIndexed { _, appId, _ ->
val hasAppId = appId in state.systemState.appIds
if (!hasAppId) {
Log.w(LOG_TAG, "Dropping unknown app ID $appId when parsing app-op state")
@@ -56,17 +56,17 @@
private fun BinaryXmlPullParser.parseAppId(userState: UserState) {
val appId = getAttributeIntOrThrow(ATTR_ID)
val appOpModes = IndexedMap<String, Int>()
- userState.uidAppOpModes[appId] = appOpModes
+ userState.appIdAppOpModes[appId] = appOpModes
parseAppOps(appOpModes)
}
override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
- serializeUidAppOps(state.userStates[userId])
+ serializeAppIdAppOps(state.userStates[userId])
}
- private fun BinaryXmlSerializer.serializeUidAppOps(userState: UserState) {
- tag(TAG_UID_APP_OPS) {
- userState.uidAppOpModes.forEachIndexed { _, appId, appOpModes ->
+ private fun BinaryXmlSerializer.serializeAppIdAppOps(userState: UserState) {
+ tag(TAG_APP_ID_APP_OPS) {
+ userState.appIdAppOpModes.forEachIndexed { _, appId, appOpModes ->
serializeAppId(appId, appOpModes)
}
}
@@ -83,10 +83,10 @@
}
companion object {
- private val LOG_TAG = UidAppOpPersistence::class.java.simpleName
+ private val LOG_TAG = AppIdAppOpPersistence::class.java.simpleName
private const val TAG_APP_ID = "app-id"
- private const val TAG_UID_APP_OPS = "uid-app-ops"
+ private const val TAG_APP_ID_APP_OPS = "app-id-app-ops"
private const val ATTR_ID = "id"
}
diff --git a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
similarity index 90%
rename from services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt
rename to services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
index 0ba9a1e..5a2522e 100644
--- a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
@@ -24,7 +24,7 @@
import com.android.server.permission.access.UidUri
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) {
+class AppIdAppOpPolicy : BaseAppOpPolicy(AppIdAppOpPersistence()) {
@Volatile
private var onAppOpModeChangedListeners = IndexedListSet<OnAppOpModeChangedListener>()
private val onAppOpModeChangedListenersLock = Any()
@@ -54,18 +54,18 @@
override fun MutateStateScope.onAppIdRemoved(appId: Int) {
newState.userStates.forEachIndexed { _, _, userState ->
- userState.uidAppOpModes -= appId
+ userState.appIdAppOpModes -= appId
userState.requestWrite()
// Skip notifying the change listeners since the app ID no longer exists.
}
}
fun GetStateScope.getAppOpModes(appId: Int, userId: Int): IndexedMap<String, Int>? =
- state.userStates[userId].uidAppOpModes[appId]
+ state.userStates[userId].appIdAppOpModes[appId]
fun MutateStateScope.removeAppOpModes(appId: Int, userId: Int): Boolean {
val userState = newState.userStates[userId]
- val isChanged = userState.uidAppOpModes.removeReturnOld(appId) != null
+ val isChanged = userState.appIdAppOpModes.removeReturnOld(appId) != null
if (isChanged) {
userState.requestWrite()
}
@@ -73,7 +73,7 @@
}
fun GetStateScope.getAppOpMode(appId: Int, userId: Int, appOpName: String): Int =
- state.userStates[userId].uidAppOpModes[appId]
+ state.userStates[userId].appIdAppOpModes[appId]
.getWithDefault(appOpName, AppOpsManager.opToDefaultMode(appOpName))
fun MutateStateScope.setAppOpMode(
@@ -83,8 +83,8 @@
mode: Int
): Boolean {
val userState = newState.userStates[userId]
- val uidAppOpModes = userState.uidAppOpModes
- var appOpModes = uidAppOpModes[appId]
+ val appIdAppOpModes = userState.appIdAppOpModes
+ var appOpModes = appIdAppOpModes[appId]
val defaultMode = AppOpsManager.opToDefaultMode(appOpName)
val oldMode = appOpModes.getWithDefault(appOpName, defaultMode)
if (oldMode == mode) {
@@ -92,11 +92,11 @@
}
if (appOpModes == null) {
appOpModes = IndexedMap()
- uidAppOpModes[appId] = appOpModes
+ appIdAppOpModes[appId] = appOpModes
}
appOpModes.putWithDefault(appOpName, mode, defaultMode)
if (appOpModes.isEmpty()) {
- uidAppOpModes -= appId
+ appIdAppOpModes -= appId
}
userState.requestWrite()
onAppOpModeChangedListeners.forEachIndexed { _, it ->
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
index af85eba..4caf6cc 100644
--- a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
@@ -47,7 +47,7 @@
private val packagePolicy = service.getSchemePolicy(PackageUri.SCHEME, AppOpUri.SCHEME)
as PackageAppOpPolicy
private val uidPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME)
- as UidAppOpPolicy
+ as AppIdAppOpPolicy
private val context = service.context
private lateinit var handler: Handler
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionMigration.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt
similarity index 96%
rename from services/permission/java/com/android/server/permission/access/permission/UidPermissionMigration.kt
rename to services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt
index 8a7697c..0a2fad9 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionMigration.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt
@@ -25,7 +25,7 @@
/**
* This class migrate legacy permissions to unified permission subsystem
*/
-class UidPermissionMigration {
+class AppIdPermissionMigration {
internal fun migrateSystemState(state: AccessState) {
val legacyPermissionsManager =
LocalServices.getService(PermissionMigrationHelper::class.java)!!
@@ -71,7 +71,7 @@
userId: Int
) {
val permissionFlags =
- state.userStates[userId].uidPermissionFlags.getOrPut(appId) { IndexedMap() }
+ state.userStates[userId].appIdPermissionFlags.getOrPut(appId) { IndexedMap() }
legacyPermissionStates.forEach forEachPermission@ { (permissionName, permissionState) ->
val permission = state.systemState.permissions[permissionName]
@@ -119,7 +119,7 @@
}
companion object {
- private val LOG_TAG = UidPermissionMigration::class.java.simpleName
+ private val LOG_TAG = AppIdPermissionMigration::class.java.simpleName
private const val DEBUG_MIGRATION = false
}
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
similarity index 86%
rename from services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt
rename to services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
index 35cdbce..552dda1 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
@@ -37,7 +37,7 @@
import com.android.server.permission.access.util.tag
import com.android.server.permission.access.util.tagName
-class UidPermissionPersistence {
+class AppIdPermissionPersistence {
fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
val systemState = state.systemState
when (tagName) {
@@ -126,12 +126,12 @@
fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
when (tagName) {
- TAG_PERMISSIONS -> parsePermissionFlags(state, userId)
+ TAG_APP_ID_PERMISSIONS -> parseAppIdPermissions(state, userId)
else -> {}
}
}
- private fun BinaryXmlPullParser.parsePermissionFlags(state: AccessState, userId: Int) {
+ private fun BinaryXmlPullParser.parseAppIdPermissions(state: AccessState, userId: Int) {
val userState = state.userStates[userId]
forEachTag {
when (tagName) {
@@ -139,7 +139,7 @@
else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
}
}
- userState.uidPermissionFlags.retainAllIndexed { _, appId, _ ->
+ userState.appIdPermissionFlags.retainAllIndexed { _, appId, _ ->
val hasAppId = appId in state.systemState.appIds
if (!hasAppId) {
Log.w(LOG_TAG, "Dropping unknown app ID $appId when parsing permission state")
@@ -151,34 +151,34 @@
private fun BinaryXmlPullParser.parseAppId(userState: UserState) {
val appId = getAttributeIntOrThrow(ATTR_ID)
val permissionFlags = IndexedMap<String, Int>()
- userState.uidPermissionFlags[appId] = permissionFlags
- parseAppIdPermissions(permissionFlags)
+ userState.appIdPermissionFlags[appId] = permissionFlags
+ parsePermissionStates(permissionFlags)
}
- private fun BinaryXmlPullParser.parseAppIdPermissions(
+ private fun BinaryXmlPullParser.parsePermissionStates(
permissionFlags: IndexedMap<String, Int>
) {
forEachTag {
when (tagName) {
- TAG_PERMISSION -> parseAppIdPermission(permissionFlags)
+ TAG_PERMISSION -> parsePermissionState(permissionFlags)
else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
}
}
}
- private fun BinaryXmlPullParser.parseAppIdPermission(permissionFlags: IndexedMap<String, Int>) {
+ private fun BinaryXmlPullParser.parsePermissionState(permissionFlags: IndexedMap<String, Int>) {
val name = getAttributeValueOrThrow(ATTR_NAME).intern()
val flags = getAttributeIntOrThrow(ATTR_FLAGS)
permissionFlags[name] = flags
}
fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
- serializePermissionFlags(state.userStates[userId])
+ serializeAppIdPermissions(state.userStates[userId])
}
- private fun BinaryXmlSerializer.serializePermissionFlags(userState: UserState) {
- tag(TAG_PERMISSIONS) {
- userState.uidPermissionFlags.forEachIndexed { _, appId, permissionFlags ->
+ private fun BinaryXmlSerializer.serializeAppIdPermissions(userState: UserState) {
+ tag(TAG_APP_ID_PERMISSIONS) {
+ userState.appIdPermissionFlags.forEachIndexed { _, appId, permissionFlags ->
serializeAppId(appId, permissionFlags)
}
}
@@ -190,19 +190,19 @@
) {
tag(TAG_APP_ID) {
attributeInt(ATTR_ID, appId)
- serializeAppIdPermissions(permissionFlags)
+ serializePermissionStates(permissionFlags)
}
}
- private fun BinaryXmlSerializer.serializeAppIdPermissions(
+ private fun BinaryXmlSerializer.serializePermissionStates(
permissionFlags: IndexedMap<String, Int>
) {
permissionFlags.forEachIndexed { _, name, flags ->
- serializeAppIdPermission(name, flags)
+ serializePermissionState(name, flags)
}
}
- private fun BinaryXmlSerializer.serializeAppIdPermission(name: String, flags: Int) {
+ private fun BinaryXmlSerializer.serializePermissionState(name: String, flags: Int) {
tag(TAG_PERMISSION) {
attributeInterned(ATTR_NAME, name)
attributeInt(ATTR_FLAGS, flags)
@@ -210,9 +210,10 @@
}
companion object {
- private val LOG_TAG = UidPermissionPersistence::class.java.simpleName
+ private val LOG_TAG = AppIdPermissionPersistence::class.java.simpleName
private const val TAG_APP_ID = "app-id"
+ private const val TAG_APP_ID_PERMISSIONS = "app-id-permissions"
private const val TAG_PERMISSION = "permission"
private const val TAG_PERMISSIONS = "permissions"
private const val TAG_PERMISSION_TREES = "permission-trees"
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
similarity index 98%
rename from services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
rename to services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 132b90d..6673dc6 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -45,10 +45,10 @@
import com.android.server.pm.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageState
-class UidPermissionPolicy : SchemePolicy() {
- private val persistence = UidPermissionPersistence()
+class AppIdPermissionPolicy : SchemePolicy() {
+ private val persistence = AppIdPermissionPersistence()
- private val migration = UidPermissionMigration()
+ private val migration = AppIdPermissionMigration()
@Volatile
private var onPermissionFlagsChangedListeners =
@@ -126,7 +126,7 @@
override fun MutateStateScope.onAppIdRemoved(appId: Int) {
newState.userStates.forEachValueIndexed { _, userState ->
- userState.uidPermissionFlags -= appId
+ userState.appIdPermissionFlags -= appId
userState.requestWrite()
// Skip notifying the change listeners since the app ID no longer exists.
}
@@ -596,7 +596,7 @@
requestedPermissions += it.androidPackage!!.requestedPermissions
}
newState.userStates.forEachIndexed { _, userId, userState ->
- userState.uidPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
+ userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
if (permissionName !in requestedPermissions) {
setPermissionFlags(appId, userId, permissionName, 0)
}
@@ -608,7 +608,7 @@
// If the app is updated, and has scoped storage permissions, then it is possible that the
// app updated in an attempt to get unscoped storage. If so, revoke all storage permissions.
newState.userStates.forEachIndexed { _, userId, userState ->
- userState.uidPermissionFlags[appId]?.forEachReversedIndexed {
+ userState.appIdPermissionFlags[appId]?.forEachReversedIndexed {
_, permissionName, oldFlags ->
if (permissionName !in STORAGE_AND_MEDIA_PERMISSIONS || oldFlags == 0) {
return@forEachReversedIndexed
@@ -1316,7 +1316,7 @@
}
fun GetStateScope.getUidPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? =
- state.userStates[userId]?.uidPermissionFlags?.get(appId)
+ state.userStates[userId]?.appIdPermissionFlags?.get(appId)
fun GetStateScope.getPermissionFlags(
appId: Int,
@@ -1336,7 +1336,7 @@
userId: Int,
permissionName: String
): Int =
- state.userStates[userId]?.uidPermissionFlags?.get(appId).getWithDefault(permissionName, 0)
+ state.userStates[userId]?.appIdPermissionFlags?.get(appId).getWithDefault(permissionName, 0)
fun MutateStateScope.setPermissionFlags(
appId: Int,
@@ -1354,8 +1354,8 @@
flagValues: Int
): Boolean {
val userState = newState.userStates[userId]
- val uidPermissionFlags = userState.uidPermissionFlags
- var permissionFlags = uidPermissionFlags[appId]
+ val appIdPermissionFlags = userState.appIdPermissionFlags
+ var permissionFlags = appIdPermissionFlags[appId]
val oldFlags = permissionFlags.getWithDefault(permissionName, 0)
val newFlags = (oldFlags andInv flagMask) or (flagValues and flagMask)
if (oldFlags == newFlags) {
@@ -1363,11 +1363,11 @@
}
if (permissionFlags == null) {
permissionFlags = IndexedMap()
- uidPermissionFlags[appId] = permissionFlags
+ appIdPermissionFlags[appId] = permissionFlags
}
permissionFlags.putWithDefault(permissionName, newFlags, 0)
if (permissionFlags.isEmpty()) {
- uidPermissionFlags -= appId
+ appIdPermissionFlags -= appId
}
userState.requestWrite()
onPermissionFlagsChangedListeners.forEachIndexed { _, it ->
@@ -1397,7 +1397,7 @@
}
companion object {
- private val LOG_TAG = UidPermissionPolicy::class.java.simpleName
+ private val LOG_TAG = AppIdPermissionPolicy::class.java.simpleName
private const val PLATFORM_PACKAGE_NAME = "android"
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
index 84da9b6..4b20472 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
@@ -138,7 +138,7 @@
* For example, this flag may be set in
* [com.android.server.pm.permission.DefaultPermissionGrantPolicy].
*
- * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
+ * @see PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
*/
const val PREGRANT = 1 shl 9
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index 7929245..9b69362 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -65,7 +65,7 @@
import com.android.server.permission.access.MutateStateScope
import com.android.server.permission.access.PermissionUri
import com.android.server.permission.access.UidUri
-import com.android.server.permission.access.appop.UidAppOpPolicy
+import com.android.server.permission.access.appop.AppIdAppOpPolicy
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
import com.android.server.permission.access.util.andInv
import com.android.server.permission.access.util.hasAnyBit
@@ -101,7 +101,7 @@
private val service: AccessCheckingService
) : PermissionManagerServiceInterface {
private val policy =
- service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as UidPermissionPolicy
+ service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as AppIdPermissionPolicy
private val context = service.context
private lateinit var metricsLogger: MetricsLogger
@@ -930,7 +930,8 @@
permissionName: String,
isGranted: Boolean
) {
- val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as UidAppOpPolicy
+ val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as
+ AppIdAppOpPolicy
val appOpName = AppOpsManager.permissionToOp(permissionName)
val mode = if (isGranted) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED
with(appOpPolicy) { setAppOpMode(packageState.appId, userId, appOpName, mode) }
@@ -2102,7 +2103,7 @@
* Callback invoked when interesting actions have been taken on a permission.
*/
private inner class OnPermissionFlagsChangedListener :
- UidPermissionPolicy.OnPermissionFlagsChangedListener() {
+ AppIdPermissionPolicy.OnPermissionFlagsChangedListener() {
private var isPermissionFlagsChanged = false
private val runtimePermissionChangedUids = IntSet()
diff --git a/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
new file mode 100644
index 0000000..0ad4184
--- /dev/null
+++ b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaRoute2Info;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowBluetoothAdapter;
+import org.robolectric.shadows.ShadowBluetoothDevice;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioPoliciesBluetoothRouteControllerTest {
+
+ private static final String DEVICE_ADDRESS_UNKNOWN = ":unknown:ip:address:";
+ private static final String DEVICE_ADDRESS_SAMPLE_1 = "30:59:8B:E4:C6:35";
+ private static final String DEVICE_ADDRESS_SAMPLE_2 = "0D:0D:A6:FF:8D:B6";
+ private static final String DEVICE_ADDRESS_SAMPLE_3 = "2D:9B:0C:C2:6F:78";
+ private static final String DEVICE_ADDRESS_SAMPLE_4 = "66:88:F9:2D:A8:1E";
+
+ private Context mContext;
+
+ private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+ @Mock
+ private BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+
+ @Mock
+ private BluetoothProfileMonitor mBluetoothProfileMonitor;
+
+ private AudioPoliciesBluetoothRouteController mAudioPoliciesBluetoothRouteController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Application application = ApplicationProvider.getApplicationContext();
+ mContext = application;
+
+ BluetoothManager bluetoothManager = (BluetoothManager)
+ mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+
+ BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
+ mShadowBluetoothAdapter = Shadows.shadowOf(bluetoothAdapter);
+
+ mAudioPoliciesBluetoothRouteController =
+ new AudioPoliciesBluetoothRouteController(mContext, bluetoothAdapter,
+ mBluetoothProfileMonitor, mListener) {
+ @Override
+ boolean isDeviceConnected(BluetoothDevice device) {
+ return true;
+ }
+ };
+
+ // Enable A2DP profile.
+ when(mBluetoothProfileMonitor.isProfileSupported(eq(BluetoothProfile.A2DP), any()))
+ .thenReturn(true);
+ mShadowBluetoothAdapter.setProfileConnectionState(BluetoothProfile.A2DP,
+ BluetoothProfile.STATE_CONNECTED);
+
+ mAudioPoliciesBluetoothRouteController.start(UserHandle.of(0));
+ }
+
+ @Test
+ public void getSelectedRoute_noBluetoothRoutesAvailable_returnsNull() {
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+ }
+
+ @Test
+ public void selectRoute_noBluetoothRoutesAvailable_returnsFalse() {
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_UNKNOWN)).isFalse();
+ }
+
+ @Test
+ public void selectRoute_noDeviceWithGivenAddress_returnsFalse() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_3);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_2)).isFalse();
+ }
+
+ @Test
+ public void selectRoute_deviceIsInDevicesSet_returnsTrue() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_1)).isTrue();
+ }
+
+ @Test
+ public void selectRoute_resetSelectedDevice_returnsTrue() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_1);
+ assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+ }
+
+ @Test
+ public void selectRoute_noSelectedDevice_returnsTrue() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+ }
+
+ @Test
+ public void getSelectedRoute_updateRouteFailed_returnsNull() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+ mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_3);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+ }
+
+ @Test
+ public void getSelectedRoute_updateRouteSuccessful_returnsUpdateDevice() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_4)).isTrue();
+
+ MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+ assertThat(selectedRoute.getAddress()).isEqualTo(DEVICE_ADDRESS_SAMPLE_4);
+ }
+
+ @Test
+ public void getSelectedRoute_resetSelectedRoute_returnsNull() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Device is not null now.
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+ // Rest the device.
+ mAudioPoliciesBluetoothRouteController.selectRoute(null);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute())
+ .isNull();
+ }
+
+ @Test
+ public void getTransferableRoutes_noSelectedRoute_returnsAllBluetoothDevices() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+
+ Set<String> transferableDevices = extractAddressesListFrom(
+ mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+ assertThat(transferableDevices).containsExactlyElementsIn(addresses);
+ }
+
+ @Test
+ public void getTransferableRoutes_hasSelectedRoute_returnsRoutesWithoutSelectedDevice() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+ Set<String> transferableDevices = extractAddressesListFrom(
+ mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+ assertThat(transferableDevices).containsExactly(DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2);
+ }
+
+ @Test
+ public void getAllBluetoothRoutes_hasSelectedRoute_returnsAllRoutes() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+ Set<String> bluetoothDevices = extractAddressesListFrom(
+ mAudioPoliciesBluetoothRouteController.getAllBluetoothRoutes());
+ assertThat(bluetoothDevices).containsExactlyElementsIn(addresses);
+ }
+
+ @Test
+ public void updateVolumeForDevice_setVolumeForA2DPTo25_selectedRouteVolumeIsUpdated() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+ mAudioPoliciesBluetoothRouteController.updateVolumeForDevices(
+ AudioManager.DEVICE_OUT_BLUETOOTH_A2DP, 25);
+
+ MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+ assertThat(selectedRoute.getVolume()).isEqualTo(25);
+ }
+
+ private void sendBluetoothDevicesChangedBroadcast() {
+ Intent intent = new Intent(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+ mContext.sendBroadcast(intent);
+ }
+
+ private static Set<String> extractAddressesListFrom(Collection<MediaRoute2Info> routes) {
+ Set<String> addresses = new HashSet<>();
+
+ for (MediaRoute2Info route: routes) {
+ addresses.add(route.getAddress());
+ }
+
+ return addresses;
+ }
+
+ private static Set<BluetoothDevice> generateFakeBluetoothDevicesSet(String... addresses) {
+ Set<BluetoothDevice> devices = new HashSet<>();
+
+ for (String address: addresses) {
+ devices.add(ShadowBluetoothDevice.newInstance(address));
+ }
+
+ return devices;
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index a39e021..836f858 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -566,6 +566,22 @@
}
@Test
+ public void testWriteCorruptReadPackageRestrictions() {
+ final Settings settingsUnderTest = makeSettings();
+
+ populateDistractionFlags(settingsUnderTest);
+ settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
+
+ // Corrupt primary file.
+ writeCorruptedPackageRestrictions(0);
+
+ // now read and verify
+ populateDefaultSettings(settingsUnderTest);
+ settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
+ verifyDistractionFlags(settingsUnderTest);
+ }
+
+ @Test
public void testReadWritePackageRestrictionsAsync() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
@@ -1811,6 +1827,14 @@
.getBytes());
}
+ private void writeCorruptedPackageRestrictions(final int userId) {
+ writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+ + userId + "/package-restrictions.xml"),
+ ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<package-restrictions>\n"
+ + " <pkg name=\"" + PACKAGE_NAME_1 + "\" ").getBytes());
+ }
+
private static void writeStoppedPackagesXml() {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages-stopped.xml"),
( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index bcd69fda..8582012 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -86,6 +86,9 @@
import android.os.PowerSaveState;
import android.os.SystemClock;
import android.provider.DeviceConfig;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
import androidx.test.runner.AndroidJUnit4;
@@ -119,6 +122,8 @@
private AnyMotionDetectorForTest mAnyMotionDetector;
private AppStateTrackerForTest mAppStateTracker;
private DeviceIdleController.Constants mConstants;
+ private TelephonyCallback.OutgoingEmergencyCallListener mEmergencyCallListener;
+ private TelephonyCallback.CallStateListener mCallStateListener;
private InjectorForTest mInjector;
private MockitoSession mMockingSession;
@@ -140,6 +145,8 @@
private Sensor mMotionSensor;
@Mock
private SensorManager mSensorManager;
+ @Mock
+ private TelephonyManager mTelephonyManager;
class InjectorForTest extends DeviceIdleController.Injector {
ConnectivityManager connectivityManager;
@@ -232,6 +239,11 @@
}
@Override
+ TelephonyManager getTelephonyManager() {
+ return mTelephonyManager;
+ }
+
+ @Override
boolean useMotionSensor() {
return true;
}
@@ -343,6 +355,15 @@
// Get the same Constants object that mDeviceIdleController got.
mConstants = mInjector.getConstants(mDeviceIdleController);
+
+ final ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+ verify(mTelephonyManager)
+ .registerTelephonyCallback(any(), telephonyCallbackCaptor.capture());
+ mEmergencyCallListener = (TelephonyCallback.OutgoingEmergencyCallListener)
+ telephonyCallbackCaptor.getValue();
+ mCallStateListener =
+ (TelephonyCallback.CallStateListener) telephonyCallbackCaptor.getValue();
}
@After
@@ -531,6 +552,16 @@
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyStateConditions(STATE_ACTIVE);
+
+ // All other conditions allow for going INACTIVE...
+ setAlarmSoon(false);
+ setChargingOn(false);
+ setScreenOn(false);
+ // ...except the emergency call.
+ setEmergencyCallActive(true);
+
+ mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+ verifyStateConditions(STATE_ACTIVE);
}
@Test
@@ -559,6 +590,15 @@
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ // All other conditions allow for going INACTIVE...
+ setChargingOn(false);
+ setScreenOn(false);
+ // ...except the emergency call.
+ setEmergencyCallActive(true);
+
+ mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
}
@Test
@@ -569,6 +609,7 @@
setAlarmSoon(false);
setChargingOn(false);
setScreenOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyStateConditions(STATE_INACTIVE);
@@ -613,6 +654,7 @@
setChargingOn(false);
setScreenOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
@@ -1147,6 +1189,22 @@
eq(true));
}
+ @Test
+ public void testEmergencyCallEndTriggersInactive() {
+ setAlarmSoon(false);
+ setChargingOn(false);
+ setScreenOn(false);
+ setEmergencyCallActive(true);
+
+ verifyStateConditions(STATE_ACTIVE);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ setEmergencyCallActive(false);
+
+ verifyStateConditions(STATE_INACTIVE);
+ verifyLightStateConditions(LIGHT_STATE_INACTIVE);
+ }
+
///////////////// EXIT conditions ///////////////////
@Test
@@ -2096,6 +2154,75 @@
.onDeviceStationaryChanged(eq(true));
}
+ @Test
+ public void testEmergencyEndsIdle() {
+ enterDeepState(STATE_ACTIVE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_INACTIVE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_IDLE_PENDING);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_SENSING);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_LOCATING);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ // Quick doze enabled or not shouldn't affect the end state.
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(true);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(false);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_IDLE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_IDLE_MAINTENANCE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+ }
+
+ @Test
+ public void testEmergencyEndsLightIdle() {
+ enterLightState(LIGHT_STATE_ACTIVE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_INACTIVE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_IDLE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_OVERRIDE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+ }
+
private void enterDeepState(int state) {
switch (state) {
case STATE_ACTIVE:
@@ -2108,6 +2235,7 @@
setQuickDozeEnabled(true);
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
break;
case STATE_LOCATING:
@@ -2128,6 +2256,7 @@
setQuickDozeEnabled(false);
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
int count = 0;
while (mDeviceIdleController.getState() != state) {
@@ -2159,6 +2288,7 @@
enterLightState(LIGHT_STATE_ACTIVE);
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
int count = 0;
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
while (mDeviceIdleController.getLightState() != lightState) {
@@ -2177,6 +2307,7 @@
case LIGHT_STATE_OVERRIDE:
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.setLightStateForTest(lightState);
break;
default:
@@ -2188,6 +2319,14 @@
mDeviceIdleController.updateChargingLocked(on);
}
+ private void setEmergencyCallActive(boolean active) {
+ if (active) {
+ mEmergencyCallListener.onOutgoingEmergencyCall(mock(EmergencyNumber.class), 0);
+ } else {
+ mCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE);
+ }
+ }
+
private void setScreenLocked(boolean locked) {
mDeviceIdleController.keyguardShowingLocked(locked);
}
@@ -2235,6 +2374,7 @@
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_IDLE_PENDING:
assertEquals(
@@ -2244,6 +2384,7 @@
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_SENSING:
assertEquals(
@@ -2255,6 +2396,7 @@
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_LOCATING:
assertEquals(
@@ -2263,6 +2405,7 @@
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_IDLE:
if (mDeviceIdleController.hasMotionSensor()) {
@@ -2276,6 +2419,7 @@
&& !mDeviceIdleController.isKeyguardShowing());
// Light state should be OVERRIDE at this point.
verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_IDLE_MAINTENANCE:
if (mDeviceIdleController.hasMotionSensor()) {
@@ -2287,6 +2431,7 @@
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_QUICK_DOZE_DELAY:
// If quick doze is enabled, the motion listener should NOT be active.
@@ -2295,6 +2440,7 @@
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
default:
fail("Conditions for " + stateToString(expectedState) + " unknown.");
@@ -2312,6 +2458,7 @@
case LIGHT_STATE_ACTIVE:
assertTrue(
mDeviceIdleController.isCharging() || mDeviceIdleController.isScreenOn()
+ || mDeviceIdleController.isEmergencyCallActive()
// Or there's an alarm coming up soon.
|| SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM
> mAlarmManager.getNextWakeFromIdleTime());
@@ -2324,6 +2471,7 @@
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
default:
fail("Conditions for " + lightStateToString(expectedLightState) + " unknown.");
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 485ce33..0b4c70c2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -1968,6 +1968,36 @@
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_DoOne_PendingFinishAttach() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.setPendingFinishAttach(true);
+ app.mState.setHasForegroundActivities(false);
+
+ sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
+ updateOomAdj(app);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FOREGROUND_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_TopApp_PendingFinishAttach() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.setPendingFinishAttach(true);
+ app.mState.setHasForegroundActivities(true);
+
+ sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
+ updateOomAdj(app);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FOREGROUND_APP_ADJ,
+ SCHED_GROUP_TOP_APP);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_UidIdle_StopService() {
final ProcessRecord app1 = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
diff --git a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
index b214787..04f6f8b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
@@ -92,6 +92,7 @@
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 488_095,
+ /* normalizedAvailableCpuFreqKHz= */ 2_402_267,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
/* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
/* idleTimeMillis= */ 409_036_950, /* iowaitTimeMillis= */ 1_322_810,
@@ -101,6 +102,7 @@
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
+ /* normalizedAvailableCpuFreqKHz= */ 2_693_525,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
/* idleTimeMillis= */ 402_707_120, /* iowaitTimeMillis= */ 1_186_960,
@@ -111,6 +113,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 464_285,
+ /* normalizedAvailableCpuFreqKHz= */ 1_901_608,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
/* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
/* idleTimeMillis= */ 402_717_120, /* iowaitTimeMillis= */ 1_166_960,
@@ -121,6 +124,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 464_285,
+ /* normalizedAvailableCpuFreqKHz= */ 1_907_125,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_349_610,
/* niceTimeMillis= */ 7_850_930, /* systemTimeMillis= */ 52_127_050,
/* idleTimeMillis= */ 409_136_950, /* iowaitTimeMillis= */ 1_332_810,
@@ -139,6 +143,7 @@
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 419_354,
+ /* normalizedAvailableCpuFreqKHz= */ 2_425_919,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
/* idleTimeMillis= */ 110_000_000, /* iowaitTimeMillis= */ 1_100_000,
@@ -148,6 +153,7 @@
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 2_800_000,
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 429_032,
+ /* normalizedAvailableCpuFreqKHz= */ 2_403_009,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 900_000,
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
/* idleTimeMillis= */ 1_000_000, /* iowaitTimeMillis= */ 90_000,
@@ -158,6 +164,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ true, /* curCpuFreqKHz= */ 2_000_000,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 403_225,
+ /* normalizedAvailableCpuFreqKHz= */ 1_688_209,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
/* niceTimeMillis= */ 2_000_000, /* systemTimeMillis= */ 0,
/* idleTimeMillis= */ 10_000_000, /* iowaitTimeMillis= */ 1_000_000,
@@ -168,6 +175,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ false, /* curCpuFreqKHz= */ MISSING_FREQUENCY,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ MISSING_FREQUENCY,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 2_000_000,
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 1_000_000,
/* idleTimeMillis= */ 100_000, /* iowaitTimeMillis= */ 100_000,
@@ -189,6 +197,7 @@
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 2_253_713,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
/* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
/* idleTimeMillis= */ 409_036_950, /* iowaitTimeMillis= */ 1_322_810,
@@ -198,6 +207,7 @@
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 2_492_687,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
/* idleTimeMillis= */ 402_707_120, /* iowaitTimeMillis= */ 1_186_960,
@@ -208,6 +218,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 1_788_079,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
/* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
/* idleTimeMillis= */ 402_717_120, /* iowaitTimeMillis= */ 1_166_960,
@@ -218,6 +229,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 1_799_962,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_349_610,
/* niceTimeMillis= */ 7_850_930, /* systemTimeMillis= */ 52_127_050,
/* idleTimeMillis= */ 409_136_950, /* iowaitTimeMillis= */ 1_332_810,
@@ -237,6 +249,7 @@
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 2323347,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
/* idleTimeMillis= */ 110_000_000, /* iowaitTimeMillis= */ 1_100_000,
@@ -246,6 +259,7 @@
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 2_800_000,
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 209111,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 900_000,
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
/* idleTimeMillis= */ 1_000_000, /* iowaitTimeMillis= */ 90_000,
@@ -256,6 +270,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ true, /* curCpuFreqKHz= */ 2_000_000,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 453514,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
/* niceTimeMillis= */ 2_000_000, /* systemTimeMillis= */ 0,
/* idleTimeMillis= */ 10_000_000, /* iowaitTimeMillis= */ 1_000_000,
@@ -266,6 +281,7 @@
FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
/* isOnline= */ true, /* curCpuFreqKHz= */ 2_000_000,
/* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+ /* normalizedAvailableCpuFreqKHz= */ 37728,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 2_000_000,
/* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 1_000_000,
/* idleTimeMillis= */ 100_000, /* iowaitTimeMillis= */ 100_000,
@@ -323,38 +339,8 @@
SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
- expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
- FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 3_000_000,
- /* maxCpuFreqKHz= */ 1_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
- new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
- /* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
- /* idleTimeMillis= */ 402_707_120, /* iowaitTimeMillis= */ 1_186_960,
- /* irqTimeMillis= */ 14_786_940, /* softirqTimeMillis= */ 1_498_130,
- /* stealTimeMillis= */ 78_780, /* guestTimeMillis= */ 0,
- /* guestNiceTimeMillis= */ 0)));
- expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
- FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
- /* isOnline= */ true, /* curCpuFreqKHz= */ 9, /* maxCpuFreqKHz= */ 2,
- /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
- new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
- /* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
- /* idleTimeMillis= */ 402_717_120, /* iowaitTimeMillis= */ 1_166_960,
- /* irqTimeMillis= */ 14_796_940, /* softirqTimeMillis= */ 1_478_130,
- /* stealTimeMillis= */ 88_780, /* guestTimeMillis= */ 0,
- /* guestNiceTimeMillis= */ 0)));
- expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
- FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
- /* isOnline= */ true, /* curCpuFreqKHz= */ 9, /* maxCpuFreqKHz= */ 2,
- /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
- new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_349_610,
- /* niceTimeMillis= */ 7_850_930, /* systemTimeMillis= */ 52_127_050,
- /* idleTimeMillis= */ 409_136_950, /* iowaitTimeMillis= */ 1_332_810,
- /* irqTimeMillis= */ 8_136_740, /* softirqTimeMillis= */ 438_970,
- /* stealTimeMillis= */ 71_950, /* guestTimeMillis= */ 0,
- /* guestNiceTimeMillis= */ 0)));
- compareCpuInfos("CPU infos with corrupted CPU frequency", expectedCpuInfos,
- actualCpuInfos);
+ compareCpuInfos("CPU infos with corrupted CPU frequency", expectedCpuInfos, actualCpuInfos);
}
@Test
@@ -368,6 +354,7 @@
expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
/* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 488_095,
+ /* normalizedAvailableCpuFreqKHz= */ 2_402_267,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
/* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
/* idleTimeMillis= */ 409_036_950, /* iowaitTimeMillis= */ 1_322_810,
@@ -377,6 +364,7 @@
expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
/* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
+ /* normalizedAvailableCpuFreqKHz= */ 2_693_525,
new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
/* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
/* idleTimeMillis= */ 402_707_120, /* iowaitTimeMillis= */ 1_186_960,
@@ -393,7 +381,7 @@
assertWithMessage("Make empty dir %s", emptyDir).that(emptyDir.mkdir()).isTrue();
CpuInfoReader cpuInfoReader = new CpuInfoReader(emptyDir, getCacheFile(
VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR),
- getCacheFile(VALID_PROC_STAT));
+ getCacheFile(VALID_PROC_STAT), /* minReadIntervalMillis= */0);
assertWithMessage("Init CPU reader info").that(cpuInfoReader.init()).isFalse();
@@ -406,7 +394,7 @@
File emptyDir = getCacheFile(EMPTY_DIR);
assertWithMessage("Make empty dir %s", emptyDir).that(emptyDir.mkdir()).isTrue();
CpuInfoReader cpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR), emptyDir,
- getCacheFile(VALID_PROC_STAT));
+ getCacheFile(VALID_PROC_STAT), /* minReadIntervalMillis= */0);
assertWithMessage("Init CPU reader info").that(cpuInfoReader.init()).isFalse();
@@ -420,12 +408,32 @@
assertWithMessage("Create empty file %s", emptyFile).that(emptyFile.createNewFile())
.isTrue();
CpuInfoReader cpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
- getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR), getCacheFile(EMPTY_FILE));
+ getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR), getCacheFile(EMPTY_FILE),
+ /* minReadIntervalMillis= */0);
assertWithMessage("Cpu infos with empty proc stat").that(cpuInfoReader.readCpuInfos())
.isNull();
}
+ @Test
+ public void testReadingTooFrequentlyReturnsLastReadCpuInfos() throws Exception {
+ CpuInfoReader cpuInfoReader = new CpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
+ getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR), getCacheFile(VALID_PROC_STAT),
+ /* minReadIntervalMillis= */ 60_000);
+ assertWithMessage("Initialize CPU info reader").that(cpuInfoReader.init()).isTrue();
+
+ SparseArray<CpuInfoReader.CpuInfo> firstCpuInfos = cpuInfoReader.readCpuInfos();
+ assertWithMessage("CPU infos first snapshot").that(firstCpuInfos).isNotNull();
+ assertWithMessage("CPU infos first snapshot size").that(firstCpuInfos.size())
+ .isGreaterThan(0);
+
+ SparseArray<CpuInfoReader.CpuInfo> secondCpuInfos = cpuInfoReader.readCpuInfos();
+ compareCpuInfos("CPU infos second snapshot", firstCpuInfos, secondCpuInfos);
+
+ SparseArray<CpuInfoReader.CpuInfo> thirdCpuInfos = cpuInfoReader.readCpuInfos();
+ compareCpuInfos("CPU infos third snapshot", firstCpuInfos, thirdCpuInfos);
+ }
+
private void compareCpuInfos(String message,
SparseArray<CpuInfoReader.CpuInfo> expected,
SparseArray<CpuInfoReader.CpuInfo> actual) {
@@ -462,7 +470,8 @@
private static CpuInfoReader newCpuInfoReader(File cpusetDir, File cpuFreqDir,
File procStatFile) {
- CpuInfoReader cpuInfoReader = new CpuInfoReader(cpusetDir, cpuFreqDir, procStatFile);
+ CpuInfoReader cpuInfoReader = new CpuInfoReader(cpusetDir, cpuFreqDir, procStatFile,
+ /* minReadIntervalMillis= */ 0);
assertWithMessage("Initialize CPU info reader").that(cpuInfoReader.init()).isTrue();
return cpuInfoReader;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 96b6345..7942e24 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -64,6 +64,7 @@
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.testutils.OffsettableClock;
@@ -240,12 +241,15 @@
boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+ deviceInfo.uniqueId = uniqueId;
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+ when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+ DisplayDeviceConfig.DEFAULT_ID);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -626,6 +630,19 @@
.setLightSensorEnabled(false);
}
+ @Test
+ public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+ setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+ mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController).stop();
+ }
+
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -662,8 +679,8 @@
mBrightnessTrackerMock, brightnessSetting, () -> {},
hbmMetadata, /* bootCompleted= */ false);
- return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
- automaticBrightnessController, wakelockController,
+ return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+ animator, automaticBrightnessController, wakelockController,
screenOffBrightnessSensorController, hbmMetadata);
}
@@ -673,6 +690,7 @@
*/
private static class DisplayPowerControllerHolder {
public final DisplayPowerController2 dpc;
+ public final LogicalDisplay display;
public final DisplayPowerState displayPowerState;
public final BrightnessSetting brightnessSetting;
public final DualRampAnimator<DisplayPowerState> animator;
@@ -681,7 +699,7 @@
public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
public final HighBrightnessModeMetadata hbmMetadata;
- DisplayPowerControllerHolder(DisplayPowerController2 dpc,
+ DisplayPowerControllerHolder(DisplayPowerController2 dpc, LogicalDisplay display,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
@@ -689,6 +707,7 @@
ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
+ this.display = display;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index 28319ac..16bf2a22 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -64,6 +64,7 @@
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.testutils.OffsettableClock;
@@ -243,12 +244,15 @@
boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+ deviceInfo.uniqueId = uniqueId;
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+ when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+ DisplayDeviceConfig.DEFAULT_ID);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -630,6 +634,19 @@
.setLightSensorEnabled(false);
}
+ @Test
+ public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+ setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+ mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController).stop();
+ }
+
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -665,8 +682,9 @@
mBrightnessTrackerMock, brightnessSetting, () -> {},
hbmMetadata, /* bootCompleted= */ false);
- return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
- automaticBrightnessController, screenOffBrightnessSensorController, hbmMetadata);
+ return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+ animator, automaticBrightnessController, screenOffBrightnessSensorController,
+ hbmMetadata);
}
/**
@@ -675,6 +693,7 @@
*/
private static class DisplayPowerControllerHolder {
public final DisplayPowerController dpc;
+ public final LogicalDisplay display;
public final DisplayPowerState displayPowerState;
public final BrightnessSetting brightnessSetting;
public final DualRampAnimator<DisplayPowerState> animator;
@@ -682,13 +701,14 @@
public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
public final HighBrightnessModeMetadata hbmMetadata;
- DisplayPowerControllerHolder(DisplayPowerController dpc,
+ DisplayPowerControllerHolder(DisplayPowerController dpc, LogicalDisplay display,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
+ this.display = display;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index 7dc1935..293003d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -80,8 +80,12 @@
import android.os.RemoteException;
import android.os.WorkSource;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
import android.util.Log;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -174,6 +178,8 @@
doReturn(mResources).when(mContext).getResources();
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+ doReturn(ApplicationProvider.getApplicationContext()).when(
+ mContext).getApplicationContext();
doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
doReturn(PackageManager.PERMISSION_DENIED)
.when(mContext)
@@ -210,6 +216,8 @@
@After
public void tearDown() throws Exception {
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+ DeviceConfig.NAMESPACE_LOCATION);
LocalServices.removeServiceForTest(LocationManagerInternal.class);
// some test failures may leave the fg thread stuck, interrupt until we get out of it
@@ -1339,6 +1347,144 @@
assertThat(mManager.isVisibleToCaller()).isFalse();
}
+ @MediumTest
+ @Test
+ public void testEnableMsl_expectedBehavior() throws Exception {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+ "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+ // Create a random location and set provider location to cache necessary MSL assets.
+ Location loc = createLocation(NAME, mRandom);
+ loc.setAltitude(mRandom.nextDouble());
+ loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ Thread.sleep(1000);
+
+ // Register listener and reset provider location to capture.
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+ mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+ verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+ // Assert that MSL fields are populated.
+ Location actual = captor.getValue().get(0);
+ assertThat(actual.hasMslAltitude()).isTrue();
+ assertThat(actual.hasMslAltitudeAccuracy()).isTrue();
+ }
+
+ @MediumTest
+ @Test
+ public void testEnableMsl_noVerticalAccuracy() throws Exception {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+ "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+ // Create a random location and set provider location to cache necessary MSL assets.
+ Location loc = createLocation(NAME, mRandom);
+ loc.setAltitude(mRandom.nextDouble());
+ loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ Thread.sleep(1000);
+
+ // Register listener and reset provider location with no vertical accuracy to capture.
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+ mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+ loc.removeVerticalAccuracy();
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+ verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+ // Assert that only the MSL accuracy field is populated.
+ Location actual = captor.getValue().get(0);
+ assertThat(actual.hasMslAltitude()).isTrue();
+ assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+ }
+
+ @MediumTest
+ @Test
+ public void testEnableMsl_noAltitude() throws Exception {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+ "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+ // Create a random location and set provider location to cache necessary MSL assets.
+ Location loc = createLocation(NAME, mRandom);
+ loc.setAltitude(mRandom.nextDouble());
+ loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ Thread.sleep(1000);
+
+ // Register listener and reset provider location with no altitude to capture.
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+ mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+ loc.removeAltitude();
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+ verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+ // Assert that no MSL fields are populated.
+ Location actual = captor.getValue().get(0);
+ assertThat(actual.hasMslAltitude()).isFalse();
+ assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+ }
+
+ @MediumTest
+ @Test
+ public void testEnableMsl_invalidAltitude() throws Exception {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+ "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+ // Create a random location and set provider location to cache necessary MSL assets.
+ Location loc = createLocation(NAME, mRandom);
+ loc.setAltitude(mRandom.nextDouble());
+ loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ Thread.sleep(1000);
+
+ // Register listener and reset provider location with invalid altitude to capture.
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+ mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+ loc.setAltitude(Double.POSITIVE_INFINITY);
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+ verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+ // Assert that no MSL fields are populated.
+ Location actual = captor.getValue().get(0);
+ assertThat(actual.hasMslAltitude()).isFalse();
+ assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+ }
+
+ @MediumTest
+ @Test
+ public void testDisableMsl_expectedBehavior() throws Exception {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+ "enable_location_provider_manager_msl", Boolean.toString(false), false);
+
+ // Create a random location and set provider location to cache necessary MSL assets.
+ Location loc = createLocation(NAME, mRandom);
+ loc.setAltitude(mRandom.nextDouble());
+ loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ Thread.sleep(1000);
+
+ // Register listener and reset provider location to capture.
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+ mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+ mProvider.setProviderLocation(LocationResult.wrap(loc));
+ ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+ verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+ // Assert that no MSL fields are populated.
+ Location actual = captor.getValue().get(0);
+ assertThat(actual.hasMslAltitude()).isFalse();
+ assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+ }
+
private ILocationListener createMockLocationListener() {
return spy(new ILocationListener.Stub() {
@Override
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 3f5d113..06ba5dd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -664,7 +664,7 @@
private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) {
whenever(mocks.componentResolver.queryActivities(any(),
argThat { intent: Intent? -> intent != null && (action == intent.action) },
- nullable(), anyLong(), anyInt(), anyInt())) {
+ nullable(), anyLong(), anyInt())) {
ArrayList(activities.asList().map { info: ActivityInfo? ->
ResolveInfo().apply { activityInfo = info }
})
@@ -674,7 +674,7 @@
private fun mockQueryServices(action: String, vararg services: ServiceInfo) {
whenever(mocks.componentResolver.queryServices(any(),
argThat { intent: Intent? -> intent != null && (action == intent.action) },
- nullable(), anyLong(), anyInt(), anyInt())) {
+ nullable(), anyLong(), anyInt())) {
ArrayList(services.asList().map { info ->
ResolveInfo().apply { serviceInfo = info }
})
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
index 9aa53db..8979585 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
@@ -20,6 +20,8 @@
import static android.view.Display.INVALID_DISPLAY;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
@@ -73,8 +75,8 @@
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
// Make sure another user cannot be started on default display
- int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
- BG_VISIBLE, DEFAULT_DISPLAY);
+ int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
+ DEFAULT_DISPLAY);
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
"when user (%d) is starting on default display after it was started by user %d",
otherUserId, visibleBgUserId);
@@ -117,8 +119,8 @@
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
// Make sure another user cannot be started on default display
- int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
- BG_VISIBLE, DEFAULT_DISPLAY);
+ int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
+ DEFAULT_DISPLAY);
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
"when user (%d) is starting on default display after it was started by user %d",
otherUserId, visibleBgUserId);
@@ -127,8 +129,6 @@
listener.verify();
}
- /* TODO(b/261538337): re-add after the reverted CL is merged again
-
@Test
public void
testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnBgOnSecondaryDisplay()
@@ -226,5 +226,4 @@
listener.verify();
}
- */
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
index 1bf921c..2774803 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -44,7 +44,6 @@
import android.util.IntArray;
import android.util.Log;
-import com.android.internal.util.Preconditions;
import com.android.server.DumpableDumperRule;
import com.android.server.ExpectableTestCase;
@@ -152,6 +151,12 @@
}
@Test
+ public final void testAssignUserToDisplayOnStart_invalidUserStartMode() {
+ assertThrows(IllegalArgumentException.class, () -> mMediator
+ .assignUserToDisplayOnStart(USER_ID, USER_ID, 666, DEFAULT_DISPLAY));
+ }
+
+ @Test
public final void testStartFgUser_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
@@ -286,7 +291,7 @@
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
- assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
@@ -302,14 +307,14 @@
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
- assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
- assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
@@ -335,6 +340,41 @@
}
@Test
+ public final void testStartBgProfile_onDefaultDisplay_whenParentIsNotStarted()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForNoEvents();
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+ DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+
+ listener.verify();
+ }
+
+ @Test
+ public final void testStartBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForNoEvents();
+ startBackgroundUser(PARENT_USER_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+ DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
+
+ assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ @Test
public final void testStartBgProfile_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
@@ -488,8 +528,6 @@
* se.
*/
protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
- Preconditions.checkArgument(displayId != INVALID_DISPLAY && displayId != DEFAULT_DISPLAY,
- "must pass a secondary display, not %d", displayId);
Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
index af85ef4..e82910f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -109,34 +109,6 @@
}
@Test
- public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
- throws Exception {
- AsyncUserVisibilityListener listener = addListenerForEvents(
- onInvisible(INITIAL_CURRENT_USER_ID),
- onVisible(PARENT_USER_ID),
- onVisible(PROFILE_USER_ID));
- startForegroundUser(PARENT_USER_ID);
-
- int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
- BG_VISIBLE, DEFAULT_DISPLAY);
- assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
- expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
-
- expectUserIsVisible(PROFILE_USER_ID);
- expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
- expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
- expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
- expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
-
- expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
- expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
-
- assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
-
- listener.verify();
- }
-
- @Test
public final void testStartFgUser_onInvalidDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
@@ -301,14 +273,83 @@
}
@Test
+ public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForEvents(
+ onInvisible(INITIAL_CURRENT_USER_ID),
+ onVisible(PARENT_USER_ID),
+ onVisible(PROFILE_USER_ID));
+ startForegroundUser(PARENT_USER_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+
+ expectUserIsVisible(PROFILE_USER_ID);
+ expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+ expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
+
+ expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
+ expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
+
+ assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ @Test
public final void
- testStartVisibleBgProfile_onDefaultDisplay_whenParentVisibleOnSecondaryDisplay()
- throws Exception {
+ testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnAnotherDisplay()
+ throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ // Not supported - profiles can only be started on default display
+ @Test
+ public final void
+ testStartVisibleBgProfile_onSecondaryDisplay_whenParentIsStartedVisibleOnThatDisplay()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+ startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ @Test
+ public final void
+ testStartProfile_onDefaultDisplay_whenParentIsStartedVisibleOnSecondaryDisplay()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+ startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+ DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 3a7b9a4..6f26a5f 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -31,6 +31,7 @@
"services.backup",
"services.companion",
"services.core",
+ "services.credentials",
"services.devicepolicy",
"services.net",
"services.people",
@@ -115,6 +116,7 @@
":StubTestApp",
":SuspendTestApp",
":MediaButtonReceiverHolderTestHelperApp",
+ "data/broken_shortcut.xml",
],
java_resources: [
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index d967647..b304968 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -21,6 +21,8 @@
<option name="cleanup" value="true" />
<option name="push-file" key="SimpleServiceTestApp3.apk"
value="/data/local/tmp/cts/content/SimpleServiceTestApp3.apk" />
+ <option name="push-file" key="broken_shortcut.xml"
+ value="/data/local/tmp/cts/content/broken_shortcut.xml" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/services/tests/servicestests/data/broken_shortcut.xml b/services/tests/servicestests/data/broken_shortcut.xml
new file mode 100644
index 0000000..f2b083d
--- /dev/null
+++ b/services/tests/servicestests/data/broken_shortcut.xml
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index b89568b..caa2e36 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -25,6 +25,7 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.nullable;
import static org.mockito.Mockito.times;
@@ -38,6 +39,7 @@
import android.accounts.CantAddAccountActivity;
import android.accounts.IAccountManagerResponse;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.INotificationManager;
import android.app.PropertyInvalidatedCache;
import android.app.admin.DevicePolicyManager;
@@ -172,6 +174,16 @@
setContext(mockContext);
mTestInjector = new TestInjector(realTestContext, mockContext, mMockNotificationManager);
mAms = new AccountManagerService(mTestInjector);
+ doAnswer(invocation -> {
+ final Intent intent = invocation.getArgument(0);
+ final Bundle options = invocation.getArgument(3);
+ if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.endsWith(intent.getAction())) {
+ final BroadcastOptions bOptions = new BroadcastOptions(options);
+ assertEquals(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT,
+ bOptions.getDeliveryGroupPolicy());
+ }
+ return null;
+ }).when(mMockContext).sendBroadcastAsUser(any(), any(), any(), any());
}
@Override
@@ -3178,7 +3190,7 @@
mAccountRemovedBroadcasts = 0;
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, atLeast(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(),
- any(UserHandle.class));
+ any(UserHandle.class), any(), any());
for (Intent intent : captor.getAllValues()) {
if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) {
mVisibleAccountsChangedBroadcasts++;
@@ -3535,7 +3547,19 @@
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
- mMockContext.sendBroadcastAsUser(intent, user);
+ sendBroadcastAsUser(intent, user, null, null);
+ }
+
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
+ Bundle options) {
+ mMockContext.sendBroadcastAsUser(intent, user, receiverPermission, options);
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ return mMockContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 93dfee6..8c7b0c5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -528,7 +528,7 @@
ActivityManager.PROCESS_CAPABILITY_NONE,
ActivityManager.PROCESS_CAPABILITY_NONE,
ActivityManager.PROCESS_CAPABILITY_NONE,
- ActivityManager.PROCESS_CAPABILITY_NETWORK,
+ ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
};
final Map<Integer, ChangeRecord> changeItems = new HashMap<>();
for (int i = 0; i < changesForPendingUidRecords.length; ++i) {
diff --git a/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java b/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java
index e68a8a0..01563e2 100644
--- a/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java
@@ -106,6 +106,64 @@
mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
}
+ @Test
+ public void testStrictRepeatedLimiting() throws Exception {
+ // The first 6 entries should not be rate limited.
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ // The 7th entry of the same process should be rate limited.
+ assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+ // After 11 minutes there should be nothing left in the buffer and the same type of entry
+ // should not get rate limited anymore.
+ mClock.setOffsetMillis(11 * 60 * 1000);
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ // The first 6 entries should not be rate limited again.
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+ // The 7th entry of the same process should be rate limited.
+ assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+ // After 11 more minutes there should be nothing left in the buffer and the same type of
+ // entry should not get rate limited anymore.
+ mClock.setOffsetMillis(22 * 60 * 1000);
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+ // Repeated crashes after the last reset being rate limited should be restricted faster.
+ assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+ // We now need to wait 61 minutes for the buffer should be empty again.
+ mClock.setOffsetMillis(83 * 60 * 1000);
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+ // After yet another 61 minutes, this time without triggering rate limiting, the strict
+ // limiting should be turnd off.
+ mClock.setOffsetMillis(144 * 60 * 1000);
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+ // As rate limiting was not triggered in the last reset, after another 11 minutes the
+ // buffer should still act as normal.
+ mClock.setOffsetMillis(155 * 60 * 1000);
+ // The first 6 entries should not be rate limited.
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ // The 7th entry of the same process should be rate limited.
+ assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+ }
+
private static class TestClock implements DropboxRateLimiter.Clock {
long mOffsetMillis = 0L;
diff --git a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
index 4412cfe..8cbed2c 100644
--- a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
@@ -305,60 +305,4 @@
assertEquals("Interaction event time was not updated correctly.",
interactionEventTime, mProcessRecord.mState.getInteractionEventTime());
}
-
- private void updateShortFgsOwner(int uid, int pid, boolean add) {
- sService.mOomAdjuster.updateShortFgsOwner(uid, pid, add);
- }
-
- private void assertHasUidShortForegroundService(int uid, boolean expected) {
- assertEquals(expected, sService.mOomAdjuster.hasUidShortForegroundService(uid));
- }
-
- @Test
- public void testHasUidShortForegroundService() {
- assertHasUidShortForegroundService(1, false);
- assertHasUidShortForegroundService(2, false);
- assertHasUidShortForegroundService(3, false);
- assertHasUidShortForegroundService(100, false);
- assertHasUidShortForegroundService(101, false);
-
- updateShortFgsOwner(1, 100, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(100, false);
- assertHasUidShortForegroundService(2, false);
-
- updateShortFgsOwner(1, 101, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(101, false);
- assertHasUidShortForegroundService(2, false);
-
- updateShortFgsOwner(2, 200, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
- assertHasUidShortForegroundService(200, false);
-
- updateShortFgsOwner(1, 101, false);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(1, 99, false); // unused PID
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(1, 100, false);
- assertHasUidShortForegroundService(1, false);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(1, 100, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(2, 200, false);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, false);
-
- updateShortFgsOwner(2, 201, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
index 8a3f246..f788c92 100644
--- a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
@@ -18,8 +18,8 @@
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
@@ -185,10 +185,10 @@
verifyNoMoreInteractions(observer2);
addPendingChange(TEST_UID1, UidRecord.CHANGE_PROCSTATE | UidRecord.CHANGE_CAPABILITY,
- PROCESS_STATE_RECEIVER, 111, PROCESS_CAPABILITY_NETWORK, false);
+ PROCESS_STATE_RECEIVER, 111, PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK, false);
mUidObserverController.dispatchUidsChanged();
verify(observer2).onUidStateChanged(TEST_UID1, PROCESS_STATE_RECEIVER,
- 111, PROCESS_CAPABILITY_NETWORK);
+ 111, PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK);
verifyNoMoreInteractions(observer1);
verifyNoMoreInteractions(observer2);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index 26524d7..7646c40 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -273,16 +273,6 @@
showHideOverlay(c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
}
- @Test
- public void testPowerPressForwardsAcquireMessage() throws RemoteException {
- final FingerprintEnrollClient client = createClient();
- client.start(mCallback);
- client.onPowerPressed();
-
- verify(mClientMonitorCallbackConverter).onAcquired(anyInt(),
- eq(FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt());
- }
-
private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
throws RemoteException {
final FingerprintEnrollClient client = createClient();
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
index 760ed9b..7642e7b 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
@@ -87,7 +87,7 @@
// Allow virtual devices to be created on the looper thread for testing.
final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
- mInputController = new InputController(new Object(), mNativeWrapperMock,
+ mInputController = new InputController(mNativeWrapperMock,
new Handler(TestableLooper.get(this).getLooper()),
InstrumentationRegistry.getTargetContext().getSystemService(WindowManager.class),
threadVerifier);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 8f4c81f..2967c5c 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -18,6 +18,7 @@
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.Context.DEVICE_ID_INVALID;
@@ -117,6 +118,7 @@
import com.google.android.collect.Sets;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -355,7 +357,7 @@
TestableLooper.get(this), mNativeWrapperMock, mIInputManagerMock);
// Allow virtual devices to be created on the looper thread for testing.
final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
- mInputController = new InputController(new Object(), mNativeWrapperMock,
+ mInputController = new InputController(mNativeWrapperMock,
new Handler(TestableLooper.get(this).getLooper()),
mContext.getSystemService(WindowManager.class), threadVerifier);
mSensorController =
@@ -372,6 +374,11 @@
mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1);
}
+ @After
+ public void tearDown() {
+ mDeviceImpl.close();
+ }
+
@Test
public void getDeviceIdForDisplayId_invalidDisplayId_returnsDefault() {
assertThat(mVdm.getDeviceIdForDisplayId(Display.INVALID_DISPLAY))
@@ -444,6 +451,7 @@
.setBlockedActivities(getBlockedActivities())
.setDevicePolicy(POLICY_TYPE_SENSORS, DEVICE_POLICY_CUSTOM)
.build();
+ mDeviceImpl.close();
mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS))
@@ -451,6 +459,35 @@
}
@Test
+ public void getDevicePolicy_defaultRecentsPolicy_gwpcCanShowRecentsOnHostDevice() {
+ VirtualDeviceParams params = new VirtualDeviceParams
+ .Builder()
+ .build();
+ mDeviceImpl.close();
+ mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+
+ GenericWindowPolicyController gwpc =
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1);
+ assertThat(gwpc.canShowTasksInHostDeviceRecents()).isTrue();
+ }
+
+ @Test
+ public void getDevicePolicy_customRecentsPolicy_gwpcCannotShowRecentsOnHostDevice() {
+ VirtualDeviceParams params = new VirtualDeviceParams
+ .Builder()
+ .setDevicePolicy(POLICY_TYPE_RECENTS, DEVICE_POLICY_CUSTOM)
+ .build();
+ mDeviceImpl.close();
+ mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+
+ GenericWindowPolicyController gwpc =
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1);
+ assertThat(gwpc.canShowTasksInHostDeviceRecents()).isFalse();
+ }
+
+ @Test
public void getDeviceOwnerUid_oneDevice_returnsCorrectId() {
int ownerUid = mLocalService.getDeviceOwnerUid(mDeviceImpl.getDeviceId());
assertThat(ownerUid).isEqualTo(mDeviceImpl.getOwnerUid());
@@ -501,6 +538,7 @@
doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
+ mDeviceImpl.close();
mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
VirtualSensor sensor = mLocalService.getVirtualSensor(VIRTUAL_DEVICE_ID_1, SENSOR_HANDLE);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 7b5af1e..d9e4da7 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -90,8 +90,7 @@
/* secureWindowCallback= */ null,
/* intentListenerCallback= */ null,
/* displayCategories= */ new ArrayList<>(),
- /* recentsPolicy= */
- VirtualDeviceParams.RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS);
+ /* showTasksInHostDeviceRecents= */ true);
}
diff --git a/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java b/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java
new file mode 100644
index 0000000..b7085f15
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 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.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.credentials.CredentialDescription;
+import android.credentials.RegisterCredentialDescriptionRequest;
+import android.service.credentials.CredentialEntry;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Tests for CredentialDescriptionRegistry.
+ *
+ * atest FrameworksServicesTests:com.android.server.credentials.CredentialDescriptionRegistryTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CredentialDescriptionRegistryTest {
+
+ private static final int USER_ID_1 = 1;
+ private static final int USER_ID_2 = 2;
+ private static final String CALLING_PACKAGE_NAME = "com.credman.app";
+ private static final String CALLING_PACKAGE_NAME_2 = "com.credman.app2";
+ private static final String MDOC_CREDENTIAL_TYPE = "MDOC";
+ private static final String PASSKEY_CREDENTIAL_TYPE = "PASSKEY";
+ private static final String FLATTENED_REQUEST = "FLATTENED_REQ";
+ private static final String FLATTENED_REQUEST_2 = "FLATTENED_REQ_2";
+
+ private CredentialDescriptionRegistry mCredentialDescriptionRegistry;
+ private CredentialEntry mEntry;
+ private CredentialEntry mEntry2;
+ private CredentialEntry mEntry3;
+
+ @SuppressWarnings("GuardedBy")
+ @Before
+ public void setUp() {
+ CredentialDescriptionRegistry.clearAllSessions();
+ mEntry = mock(CredentialEntry.class);
+ mEntry2 = mock(CredentialEntry.class);
+ mEntry3 = mock(CredentialEntry.class);
+ when(mEntry.getType()).thenReturn(MDOC_CREDENTIAL_TYPE);
+ when(mEntry2.getType()).thenReturn(MDOC_CREDENTIAL_TYPE);
+ when(mEntry3.getType()).thenReturn(PASSKEY_CREDENTIAL_TYPE);
+ mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(USER_ID_1);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testForUser_createsUniqueInstanceForEachUserID() {
+ final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+ .forUser(USER_ID_2);
+
+ assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testForUser_returnsSameInstanceForSameUserID() {
+ final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+ .forUser(USER_ID_1);
+
+ assertThat(mCredentialDescriptionRegistry).isSameInstanceAs(secondRegistry);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testClearUserSession_removesExistingSessionForUserID() {
+ CredentialDescriptionRegistry.clearUserSession(USER_ID_1);
+ final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+ .forUser(USER_ID_1);
+
+ assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry);
+ }
+
+ @Test
+ public void testEvictProvider_existingProviders_succeeds() {
+ final CredentialDescription credentialDescription =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+ new RegisterCredentialDescriptionRequest(credentialDescription);
+ final CredentialDescription credentialDescription2 =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST_2,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 =
+ new RegisterCredentialDescriptionRequest(credentialDescription2);
+
+
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME);
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest2,
+ CALLING_PACKAGE_NAME);
+ mCredentialDescriptionRegistry.evictProviderWithPackageName(CALLING_PACKAGE_NAME);
+ Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry
+ .getMatchingProviders(Set.of(FLATTENED_REQUEST));
+
+ assertThat(providers).isEmpty();
+ }
+
+ @Test
+ public void testGetMatchingProviders_existingProviders_succeeds() {
+ final CredentialDescription credentialDescription =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+ new RegisterCredentialDescriptionRequest(credentialDescription);
+ final CredentialDescription credentialDescription2 =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 =
+ new RegisterCredentialDescriptionRequest(credentialDescription2);
+
+
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest,
+ CALLING_PACKAGE_NAME);
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest2,
+ CALLING_PACKAGE_NAME_2);
+
+ Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry
+ .getMatchingProviders(Set.of(FLATTENED_REQUEST));
+ Set<String> packageNames = providers.stream().map(
+ filterResult -> filterResult.mPackageName).collect(Collectors.toSet());
+
+ assertThat(providers).hasSize(2);
+ assertThat(packageNames).contains(CALLING_PACKAGE_NAME);
+ assertThat(packageNames).contains(CALLING_PACKAGE_NAME_2);
+ }
+
+ @Test
+ public void testExecuteRegisterRequest_noProviders_filterSucceedsWithNoResults() {
+ List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry
+ .getFilteredResultForProvider(CALLING_PACKAGE_NAME,
+ FLATTENED_REQUEST).stream().toList();
+
+ assertThat(results).isEmpty();
+ }
+
+ @Test
+ public void testExecuteRegisterRequest_existingProviders_filterSucceeds() {
+ final CredentialDescription credentialDescription =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE,
+ FLATTENED_REQUEST,
+ List.of(mEntry, mEntry2));
+ final CredentialDescription credentialDescription2 =
+ new CredentialDescription(PASSKEY_CREDENTIAL_TYPE,
+ FLATTENED_REQUEST_2,
+ List.of(mEntry3));
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+ new RegisterCredentialDescriptionRequest(Set.of(credentialDescription,
+ credentialDescription2));
+
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME);
+
+ List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry
+ .getFilteredResultForProvider(CALLING_PACKAGE_NAME, FLATTENED_REQUEST)
+ .stream().toList();
+
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).mCredentialEntries).hasSize(2);
+ assertThat(results.get(0).mCredentialEntries.get(0)).isSameInstanceAs(mEntry);
+ assertThat(results.get(0).mCredentialEntries.get(1)).isSameInstanceAs(mEntry2);
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/credentials/OWNERS b/services/tests/servicestests/src/com/android/server/credentials/OWNERS
new file mode 100644
index 0000000..cc73854
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/credentials/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
index a380eff..e74b278 100644
--- a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
@@ -157,6 +157,26 @@
assertEquals(testLayout, configLayout);
}
+ @Test
+ public void testRefreshRateThermalThrottlingMapId() {
+ Layout configLayout = mDeviceStateToLayoutMap.get(4);
+
+ Layout testLayout = new Layout();
+ Layout.Display display1 = testLayout.createDisplayLocked(
+ DisplayAddress.fromPhysicalDisplayId(345L), /* isDefault= */ true,
+ /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
+ /* brightnessThrottlingMapId= */ null,
+ /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+ display1.setRefreshRateThermalThrottlingMapId("test2");
+ testLayout.createDisplayLocked(
+ DisplayAddress.fromPhysicalDisplayId(678L), /* isDefault= */ false,
+ /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
+ /* brightnessThrottlingMapId= */ null,
+ /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+
+ assertEquals(testLayout, configLayout);
+ }
+
////////////////////
// Helper Methods //
////////////////////
@@ -221,6 +241,19 @@
+ "<address>678</address>\n"
+ "</display>\n"
+ "</layout>\n"
+
+ + "<layout>\n"
+ + "<state>4</state> \n"
+ + "<display enabled=\"true\" defaultDisplay=\"true\" >\n"
+ + "<address>345</address>\n"
+ + "<refreshRateThermalThrottlingMapId>"
+ + "test2"
+ + "</refreshRateThermalThrottlingMapId>"
+ + "</display>\n"
+ + "<display enabled=\"true\">\n"
+ + "<address>678</address>\n"
+ + "</display>\n"
+ + "</layout>\n"
+ "</layouts>\n";
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index fdfcd81..45f1037 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
@@ -28,6 +29,9 @@
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.os.Temperature;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -82,6 +86,7 @@
public void testConfigValuesFromDisplayConfig() throws IOException {
setupDisplayDeviceConfigFromDisplayConfigFile();
+ assertEquals(mDisplayDeviceConfig.getName(), "Example Display");
assertEquals(mDisplayDeviceConfig.getAmbientHorizonLong(), 5000);
assertEquals(mDisplayDeviceConfig.getAmbientHorizonShort(), 50);
assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000);
@@ -237,6 +242,7 @@
@Test
public void testConfigValuesFromConfigResource() {
setupDisplayDeviceConfigFromConfigResourceFile();
+ assertNull(mDisplayDeviceConfig.getName());
assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new
float[]{2.0f, 200.0f, 600.0f}, ZERO_DELTA);
assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new
@@ -315,9 +321,59 @@
// HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
}
+ @Test
+ public void testRefreshRateThermalThrottlingFromDisplayConfig() throws IOException {
+ setupDisplayDeviceConfigFromDisplayConfigFile();
+
+ SparseArray<SurfaceControl.RefreshRateRange> defaultMap =
+ mDisplayDeviceConfig.getRefreshRateThrottlingData(null);
+ assertNotNull(defaultMap);
+ assertEquals(2, defaultMap.size());
+ assertEquals(30, defaultMap.get(Temperature.THROTTLING_CRITICAL).min, SMALL_DELTA);
+ assertEquals(60, defaultMap.get(Temperature.THROTTLING_CRITICAL).max, SMALL_DELTA);
+ assertEquals(0, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).min, SMALL_DELTA);
+ assertEquals(30, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).max, SMALL_DELTA);
+
+ SparseArray<SurfaceControl.RefreshRateRange> testMap =
+ mDisplayDeviceConfig.getRefreshRateThrottlingData("test");
+ assertNotNull(testMap);
+ assertEquals(1, testMap.size());
+ assertEquals(60, testMap.get(Temperature.THROTTLING_EMERGENCY).min, SMALL_DELTA);
+ assertEquals(90, testMap.get(Temperature.THROTTLING_EMERGENCY).max, SMALL_DELTA);
+ }
+
+ private String getRefreshThermalThrottlingMaps() {
+ return "<refreshRateThrottlingMap>\n"
+ + " <refreshRateThrottlingPoint>\n"
+ + " <thermalStatus>critical</thermalStatus>\n"
+ + " <refreshRateRange>\n"
+ + " <minimum>30</minimum>\n"
+ + " <maximum>60</maximum>\n"
+ + " </refreshRateRange>\n"
+ + " </refreshRateThrottlingPoint>\n"
+ + " <refreshRateThrottlingPoint>\n"
+ + " <thermalStatus>shutdown</thermalStatus>\n"
+ + " <refreshRateRange>\n"
+ + " <minimum>0</minimum>\n"
+ + " <maximum>30</maximum>\n"
+ + " </refreshRateRange>\n"
+ + " </refreshRateThrottlingPoint>\n"
+ + "</refreshRateThrottlingMap>\n"
+ + "<refreshRateThrottlingMap id=\"test\">\n"
+ + " <refreshRateThrottlingPoint>\n"
+ + " <thermalStatus>emergency</thermalStatus>\n"
+ + " <refreshRateRange>\n"
+ + " <minimum>60</minimum>\n"
+ + " <maximum>90</maximum>\n"
+ + " </refreshRateRange>\n"
+ + " </refreshRateThrottlingPoint>\n"
+ + "</refreshRateThrottlingMap>\n";
+ }
+
private String getContent() {
return "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<displayConfiguration>\n"
+ + "<name>Example Display</name>"
+ "<screenBrightnessMap>\n"
+ "<point>\n"
+ "<value>0.0</value>\n"
@@ -557,6 +613,7 @@
+ "<brightness>0.0125</brightness>\n"
+ "</brightnessThrottlingPoint>\n"
+ "</brightnessThrottlingMap>\n"
+ + getRefreshThermalThrottlingMaps()
+ "</thermalThrottling>\n"
+ "<refreshRate>\n"
+ "<defaultRefreshRate>45</defaultRefreshRate>\n"
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1b6b143..7971fd7 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -28,6 +28,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -127,6 +128,10 @@
private Context mContext;
+ private int mHdrConversionMode;
+
+ private int mPreferredHdrOutputType;
+
private final DisplayManagerService.Injector mShortMockedInjector =
new DisplayManagerService.Injector() {
@Override
@@ -176,6 +181,8 @@
@Override
int setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
int[] autoHdrTypes) {
+ mHdrConversionMode = conversionMode;
+ mPreferredHdrOutputType = preferredHdrOutputType;
return Display.HdrCapabilities.HDR_TYPE_INVALID;
}
@@ -185,7 +192,7 @@
}
boolean getHdrOutputConversionSupport() {
- return false;
+ return true;
}
}
@@ -1541,6 +1548,40 @@
new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
}
+ @Test
+ public void testCreateHdrConversionMode_withInvalidArguments_throwsException() {
+ assertThrows(
+ "preferredHdrOutputType must not be set if the conversion mode is "
+ + "HDR_CONVERSION_PASSTHROUGH",
+ IllegalArgumentException.class,
+ () -> new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH,
+ Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION));
+ }
+
+ @Test
+ public void testSetHdrConversionModeInternal_withInvalidArguments_throwsException() {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ assertThrows("Expected DisplayManager to throw IllegalArgumentException when "
+ + "preferredHdrOutputType is set and the conversion mode is "
+ + "HDR_CONVERSION_SYSTEM",
+ IllegalArgumentException.class,
+ () -> displayManager.setHdrConversionModeInternal(new HdrConversionMode(
+ HdrConversionMode.HDR_CONVERSION_SYSTEM,
+ Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)));
+ }
+
+ @Test
+ public void testSetAndGetHdrConversionModeInternal() {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ final HdrConversionMode mode = new HdrConversionMode(
+ HdrConversionMode.HDR_CONVERSION_FORCE,
+ Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION);
+ displayManager.setHdrConversionModeInternal(mode);
+ assertEquals(mode, displayManager.getHdrConversionModeSettingInternal());
+ assertEquals(mode.getConversionMode(), mHdrConversionMode);
+ assertEquals(mode.getPreferredHdrOutputType(), mPreferredHdrOutputType);
+ }
+
private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
throws Exception {
DisplayManagerService displayManager =
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index b698cdf..9eb6003 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -687,10 +687,10 @@
assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device1)
.getBrightnessThrottlingDataIdLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device2)
.getBrightnessThrottlingDataIdLocked());
@@ -700,10 +700,10 @@
assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device1)
.getBrightnessThrottlingDataIdLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device2)
.getBrightnessThrottlingDataIdLocked());
}
diff --git a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
index bbed1b6..618ab1b 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
@@ -34,6 +34,7 @@
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.hardware.display.ColorDisplayManager;
+import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.Time;
import android.os.Handler;
import android.os.UserHandle;
@@ -77,6 +78,7 @@
private MockTwilightManager mTwilightManager;
private DisplayTransformManager mDisplayTransformManager;
+ private DisplayManagerInternal mDisplayManagerInternal;
private ColorDisplayService mCds;
private ColorDisplayService.BinderService mBinderService;
@@ -116,6 +118,10 @@
doReturn(true).when(mDisplayTransformManager).needsLinearColorMatrix();
LocalServices.addService(DisplayTransformManager.class, mDisplayTransformManager);
+ mDisplayManagerInternal = Mockito.mock(DisplayManagerInternal.class);
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternal);
+
mCds = new ColorDisplayService(mContext);
mBinderService = mCds.new BinderService();
LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
@@ -142,6 +148,7 @@
FakeSettingsProvider.clearSettingsProvider();
LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index f256c8a..1b02799 100644
--- a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -59,12 +59,12 @@
import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
import android.os.Handler;
import android.os.IThermalEventListener;
-import android.os.IThermalService;
import android.os.Looper;
import android.os.RemoteException;
import android.os.Temperature;
@@ -75,6 +75,7 @@
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Display;
+import android.view.DisplayInfo;
import android.view.SurfaceControl.RefreshRateRange;
import android.view.SurfaceControl.RefreshRateRanges;
@@ -83,6 +84,7 @@
import com.android.internal.R;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.Preconditions;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
@@ -140,8 +142,6 @@
public SensorManagerInternal mSensorManagerInternalMock;
@Mock
public DisplayManagerInternal mDisplayManagerInternalMock;
- @Mock
- public IThermalService mThermalServiceMock;
@Before
public void setUp() throws Exception {
@@ -150,7 +150,6 @@
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
when(mContext.getContentResolver()).thenReturn(resolver);
mInjector = spy(new FakesInjector());
- when(mInjector.getThermalService()).thenReturn(mThermalServiceMock);
mHandler = new Handler(Looper.getMainLooper());
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
@@ -1773,11 +1772,12 @@
ArgumentCaptor<DisplayListener> DisplayCaptor =
ArgumentCaptor.forClass(DisplayListener.class);
- verify(mInjector).registerDisplayListener(DisplayCaptor.capture(), any(Handler.class),
+ verify(mInjector, times(2)).registerDisplayListener(DisplayCaptor.capture(),
+ any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED
| DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
- DisplayListener displayListener = DisplayCaptor.getValue();
+ DisplayListener displayListener = DisplayCaptor.getAllValues().get(0);
// Verify that there is no proximity vote initially
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
@@ -2236,8 +2236,7 @@
ArgumentCaptor<IThermalEventListener> thermalEventListener =
ArgumentCaptor.forClass(IThermalEventListener.class);
- verify(mThermalServiceMock).registerThermalEventListenerWithType(
- thermalEventListener.capture(), eq(Temperature.TYPE_SKIN));
+ verify(mInjector).registerThermalServiceListener(thermalEventListener.capture());
final IThermalEventListener listener = thermalEventListener.getValue();
// Verify that there is no skin temperature vote initially.
@@ -2246,11 +2245,13 @@
// Set the skin temperature to critical and verify that we added a vote.
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
+ BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
assertVoteForRenderFrameRateRange(vote, 0f, 60.f);
// Set the skin temperature to severe and verify that the vote is gone.
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
+ BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
assertNull(vote);
}
@@ -2709,6 +2710,16 @@
public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {}
@Override
+ public Display[] getDisplays() {
+ return new Display[] { createDisplay(DISPLAY_ID) };
+ }
+
+ @Override
+ public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+ return false;
+ }
+
+ @Override
public BrightnessInfo getBrightnessInfo(int displayId) {
return null;
}
@@ -2719,8 +2730,8 @@
}
@Override
- public IThermalService getThermalService() {
- return null;
+ public boolean registerThermalServiceListener(IThermalEventListener listener) {
+ return true;
}
@Override
@@ -2728,6 +2739,11 @@
return true;
}
+ protected Display createDisplay(int id) {
+ return new Display(DisplayManagerGlobal.getInstance(), id, new DisplayInfo(),
+ ApplicationProvider.getApplicationContext().getResources());
+ }
+
void notifyPeakRefreshRateChanged() {
if (mPeakRefreshRateObserver != null) {
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
new file mode 100644
index 0000000..dd0cd96
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2023 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.display.mode;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.testutils.TestHandler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Tests for DisplayModeDirector.SkinThermalStatusObserver. Comply with changes described in
+ * b/266789924
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SkinThermalStatusObserverTest {
+ private static final float FLOAT_TOLERANCE = 0.01f;
+ private static final int DISPLAY_ID = 1;
+ private static final int DISPLAY_ID_OTHER = 2;
+
+ SkinThermalStatusObserver mObserver;
+
+ private RegisteringFakesInjector mInjector = new RegisteringFakesInjector();
+
+ private final TestHandler mHandler = new TestHandler(null);
+ private final FakeVoteStorage mStorage = new FakeVoteStorage();
+
+ @Before
+ public void setUp() {
+ mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+ }
+
+ @Test
+ public void testRegisterListenersOnObserve() {
+ // GIVEN thermal sensor is available
+ assertNull(mInjector.mThermalEventListener);
+ assertNull(mInjector.mDisplayListener);
+ // WHEN observe is called
+ mObserver.observe();
+ // THEN thermal and display listeners are registered
+ assertEquals(mObserver, mInjector.mThermalEventListener);
+ assertEquals(mObserver, mInjector.mDisplayListener);
+ }
+
+ @Test
+ public void testFailToRegisterThermalListenerOnObserve() {
+ // GIVEN thermal sensor is not available
+ mInjector = new RegisteringFakesInjector(false);
+ mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+ // WHEN observe is called
+ mObserver.observe();
+ // THEN nothing is registered
+ assertNull(mInjector.mThermalEventListener);
+ assertNull(mInjector.mDisplayListener);
+ }
+
+ @Test
+ public void testNotifyWithDefaultVotesForCritical() {
+ // GIVEN 2 displays with no thermalThrottling config
+ mObserver.observe();
+ assertEquals(0, mStorage.mVoteRegistry.size());
+
+ // WHEN thermal sensor notifies CRITICAL
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+ mHandler.flush();
+
+ // THEN 2 votes are added to storage with (0,60) render refresh rate(default behaviour)
+ assertEquals(2, mStorage.mVoteRegistry.size());
+
+ SparseArray<DisplayModeDirector.Vote> displayVotes = mStorage.mVoteRegistry.get(DISPLAY_ID);
+ assertEquals(1, displayVotes.size());
+
+ DisplayModeDirector.Vote vote = displayVotes.get(
+ DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+ assertEquals(0, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+ assertEquals(60, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+
+ SparseArray<DisplayModeDirector.Vote> otherDisplayVotes = mStorage.mVoteRegistry.get(
+ DISPLAY_ID_OTHER);
+ assertEquals(1, otherDisplayVotes.size());
+
+ vote = otherDisplayVotes.get(DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+ assertEquals(0, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+ assertEquals(60, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+ }
+
+ @Test
+ public void testNotifyWithDefaultVotesChangeFromCriticalToSevere() {
+ // GIVEN 2 displays with no thermalThrottling config AND temperature level CRITICAL
+ mObserver.observe();
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+ // WHEN thermal sensor notifies SEVERE
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+ mHandler.flush();
+ // THEN all votes with PRIORITY_SKIN_TEMPERATURE are removed from the storage
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ }
+
+ @Test
+ public void testNotifyWithDefaultVotesForSevere() {
+ // GIVEN 2 displays with no thermalThrottling config
+ mObserver.observe();
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ // WHEN thermal sensor notifies CRITICAL
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+ mHandler.flush();
+ // THEN nothing is added to the storage
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ }
+
+ @Test
+ public void testNotifiesWithConfigVotes() {
+ // GIVEN 2 displays AND one has thermalThrottling config defined
+ SparseArray<SurfaceControl.RefreshRateRange> displayConfig = new SparseArray<>();
+ displayConfig.put(Temperature.THROTTLING_MODERATE,
+ new SurfaceControl.RefreshRateRange(90.0f, 120.0f));
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> config = new SparseArray<>();
+ config.put(DISPLAY_ID, displayConfig);
+ mInjector = new RegisteringFakesInjector(true, config);
+ mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+ mObserver.observe();
+ mObserver.onDisplayChanged(DISPLAY_ID);
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ // WHEN thermal sensor notifies temperature above configured
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+ mHandler.flush();
+ // THEN vote with refreshRate from config is added to the storage
+ assertEquals(1, mStorage.mVoteRegistry.size());
+ SparseArray<DisplayModeDirector.Vote> displayVotes = mStorage.mVoteRegistry.get(DISPLAY_ID);
+ assertEquals(1, displayVotes.size());
+ DisplayModeDirector.Vote vote = displayVotes.get(
+ DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+ assertEquals(90, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+ assertEquals(120, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+ }
+
+ private static Temperature createTemperature(@Temperature.ThrottlingStatus int status) {
+ return new Temperature(40.0f, Temperature.TYPE_SKIN, "test_temp", status);
+ }
+
+
+ private static class RegisteringFakesInjector extends DisplayModeDirectorTest.FakesInjector {
+ private IThermalEventListener mThermalEventListener;
+ private DisplayManager.DisplayListener mDisplayListener;
+
+ private final boolean mRegisterThermalListener;
+ private final SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> mOverriddenConfig;
+
+
+ private RegisteringFakesInjector() {
+ this(true);
+ }
+
+ private RegisteringFakesInjector(boolean registerThermalListener) {
+ this(registerThermalListener, new SparseArray<>());
+ }
+
+ private RegisteringFakesInjector(boolean registerThermalListener,
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> overriddenConfig) {
+ mRegisterThermalListener = registerThermalListener;
+ mOverriddenConfig = overriddenConfig;
+ }
+
+ @Override
+ public boolean registerThermalServiceListener(IThermalEventListener listener) {
+ mThermalEventListener = (mRegisterThermalListener ? listener : null);
+ return mRegisterThermalListener;
+ }
+
+ @Override
+ public void registerDisplayListener(DisplayManager.DisplayListener listener,
+ Handler handler, long flag) {
+ mDisplayListener = listener;
+ }
+
+ @Override
+ public Display[] getDisplays() {
+ return new Display[] {createDisplay(DISPLAY_ID), createDisplay(DISPLAY_ID_OTHER)};
+ }
+
+ @Override
+ public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+ SparseArray<SurfaceControl.RefreshRateRange> config = mOverriddenConfig.get(displayId);
+ if (config != null) {
+ displayInfo.refreshRateThermalThrottling = config;
+ return true;
+ }
+ return false;
+ }
+ }
+
+
+ private static class FakeVoteStorage implements DisplayModeDirector.BallotBox {
+ private final SparseArray<SparseArray<DisplayModeDirector.Vote>> mVoteRegistry =
+ new SparseArray<>();
+
+ @Override
+ public void vote(int displayId, int priority, DisplayModeDirector.Vote vote) {
+ SparseArray<DisplayModeDirector.Vote> votesPerDisplay = mVoteRegistry.get(displayId);
+ if (votesPerDisplay == null) {
+ votesPerDisplay = new SparseArray<>();
+ mVoteRegistry.put(displayId, votesPerDisplay);
+ }
+ if (vote == null) {
+ votesPerDisplay.remove(priority);
+ } else {
+ votesPerDisplay.put(priority, vote);
+ }
+ if (votesPerDisplay.size() == 0) {
+ mVoteRegistry.remove(displayId);
+ }
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 4a2e5d7..9fc46c5 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -86,7 +86,6 @@
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
-import android.util.Pair;
import android.util.Range;
import com.android.internal.app.ChooserActivity;
@@ -187,7 +186,6 @@
private ShortcutInfo mShortcutInfo;
private TestInjector mInjector;
private TestLooper mLooper;
- private TestPerPackageThrottler mShortcutThrottler;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
@@ -277,9 +275,7 @@
mInjector = new TestInjector();
mLooper = new TestLooper();
- mShortcutThrottler = new TestPerPackageThrottler();
- mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper(),
- mShortcutThrottler);
+ mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
mDataManager.initialize();
when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
@@ -287,7 +283,10 @@
mShortcutInfo = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
buildPerson());
- mockGetShortcuts(Collections.singletonList(mShortcutInfo));
+ when(mShortcutServiceInternal.getShortcuts(
+ anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
+ anyInt(), anyInt(), anyInt(), anyInt()))
+ .thenReturn(Collections.singletonList(mShortcutInfo));
verify(mShortcutServiceInternal).addShortcutChangeCallback(
mShortcutChangeCallbackCaptor.capture());
mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
@@ -973,7 +972,6 @@
buildPerson());
ShortcutInfo shortcut3 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc3",
buildPerson());
- mockGetShortcuts(List.of(shortcut1, shortcut2, shortcut3));
mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
Arrays.asList(shortcut1, shortcut2, shortcut3), UserHandle.of(USER_ID_PRIMARY));
mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME,
@@ -1225,6 +1223,7 @@
eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
}
}
+
@Test
public void testUncacheOldestCachedShortcut_missingNotificationEvents() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -1234,7 +1233,6 @@
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
buildPerson());
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
- mockGetShortcuts(Collections.singletonList(shortcut));
mShortcutChangeCallback.onShortcutsAddedOrUpdated(
TEST_PKG_NAME,
Collections.singletonList(shortcut),
@@ -1254,6 +1252,7 @@
eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
}
}
+
@Test
public void testUncacheOldestCachedShortcut_legacyConversation() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -1275,7 +1274,6 @@
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
buildPerson());
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
- mockGetShortcuts(Collections.singletonList(shortcut));
mShortcutChangeCallback.onShortcutsAddedOrUpdated(
TEST_PKG_NAME,
Collections.singletonList(shortcut),
@@ -1313,8 +1311,7 @@
mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
byte[] payload = mDataManager.getBackupPayload(USER_ID_PRIMARY);
- DataManager dataManager = new DataManager(
- mContext, mInjector, mLooper.getLooper(), mShortcutThrottler);
+ DataManager dataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
dataManager.onUserUnlocked(USER_ID_PRIMARY);
dataManager.restore(USER_ID_PRIMARY, payload);
ConversationInfo conversationInfo = dataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
@@ -1726,13 +1723,6 @@
return (queryFlags & flag) != 0;
}
- private void mockGetShortcuts(List<ShortcutInfo> shortcutInfoList) {
- when(mShortcutServiceInternal.getShortcuts(
- anyInt(), anyString(), anyLong(), anyString(), any(), any(), any(),
- anyInt(), anyInt(), anyInt(), anyInt()))
- .thenReturn(shortcutInfoList);
- }
-
// "Sends" a notification to a non-customized notification channel - the notification channel
// is something generic like "messages" and the notification has a shortcut id
private void sendGenericNotification() {
@@ -1994,11 +1984,4 @@
return mUsageStatsQueryHelper;
}
}
-
- private static class TestPerPackageThrottler implements PerPackageThrottler {
- @Override
- public void scheduleDebounced(Pair<String, Integer> pkgUserId, Runnable runnable) {
- runnable.run();
- }
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java
deleted file mode 100644
index 672cbb9..0000000
--- a/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2023 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.people.data;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.util.Pair;
-
-import com.android.server.testutils.OffsettableClock;
-import com.android.server.testutils.TestHandler;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-@RunWith(JUnit4.class)
-public class PerPackageThrottlerImplTest {
- private static final int DEBOUNCE_INTERVAL = 500;
- private static final String PKG_ONE = "pkg_one";
- private static final String PKG_TWO = "pkg_two";
- private static final int USER_ID = 10;
-
- private final OffsettableClock mClock = new OffsettableClock.Stopped();
- private final TestHandler mTestHandler = new TestHandler(null, mClock);
- private PerPackageThrottlerImpl mThrottler;
-
- @Before
- public void setUp() {
- mThrottler = new PerPackageThrottlerImpl(mTestHandler, DEBOUNCE_INTERVAL);
- }
-
- @Test
- public void scheduleDebounced() {
- AtomicBoolean pkgOneRan = new AtomicBoolean();
- AtomicBoolean pkgTwoRan = new AtomicBoolean();
-
- mThrottler.scheduleDebounced(new Pair<>(PKG_ONE, USER_ID), () -> pkgOneRan.set(true));
- mThrottler.scheduleDebounced(new Pair<>(PKG_ONE, USER_ID), () -> pkgOneRan.set(true));
- mThrottler.scheduleDebounced(new Pair<>(PKG_TWO, USER_ID), () -> pkgTwoRan.set(true));
- mThrottler.scheduleDebounced(new Pair<>(PKG_TWO, USER_ID), () -> pkgTwoRan.set(true));
-
- assertFalse(pkgOneRan.get());
- assertFalse(pkgTwoRan.get());
- mClock.fastForward(DEBOUNCE_INTERVAL);
- mTestHandler.timeAdvance();
- assertTrue(pkgOneRan.get());
- assertTrue(pkgTwoRan.get());
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 0a718e3..e65f8cf 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -4007,6 +4007,18 @@
// TODO Check all other fields
}
+ public void testLoadCorruptedShortcuts() throws Exception {
+ initService();
+
+ addPackage("com.android.chrome", 0, 0);
+
+ ShortcutUser user = new ShortcutUser(mService, 0);
+
+ File corruptedShortcutPackage = new File("/data/local/tmp/cts/content/",
+ "broken_shortcut.xml");
+ assertNull(ShortcutPackage.loadFromFile(mService, user, corruptedShortcutPackage, false));
+ }
+
public void testSaveCorruptAndLoadUser() throws Exception {
// First, create some shortcuts and save.
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
@@ -4096,11 +4108,12 @@
// Save and corrupt the primary files.
mService.saveDirtyInfo();
- try (Writer os = new FileWriter(mService.getUserFile(UserHandle.USER_SYSTEM))) {
+ try (Writer os = new FileWriter(
+ mService.getUserFile(UserHandle.USER_SYSTEM).getBaseFile())) {
os.write("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<user locales=\"en\" last-app-scan-time2=\"14400000");
}
- try (Writer os = new FileWriter(mService.getUserFile(USER_10))) {
+ try (Writer os = new FileWriter(mService.getUserFile(USER_10).getBaseFile())) {
os.write("<?xml version='1.0' encoding='utf");
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 15fd73c..01e56a0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -2349,7 +2349,7 @@
* can still be read.
*/
public void testLoadLegacySavedFile() throws Exception {
- final File path = mService.getUserFile(USER_0);
+ final File path = mService.getUserFile(USER_0).getBaseFile();
path.getParentFile().mkdirs();
try (Writer w = new FileWriter(path)) {
w.write(readTestAsset("shortcut/shortcut_legacy_file.xml"));
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
index 4434a32..32c9e75 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
@@ -121,4 +121,31 @@
assertEquals("Couldn't get main user.", mOutStream.toString().trim());
}
+ @Test
+ public void testCanSwitchToHeadlessSystemUser() {
+ doReturn(true).when(mUserManagerService).canSwitchToHeadlessSystemUser();
+ doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+ assertEquals(0, mCommand.exec(mBinder, in, out, err,
+ new String[]{"can-switch-to-headless-system-user"},
+ mShellCallback, mResultReceiver));
+
+ mWriter.flush();
+ assertEquals("true", mOutStream.toString().trim());
+ }
+
+
+ @Test
+ public void testIsMainUserPermanentAdmin() {
+ doReturn(false).when(mUserManagerService).isMainUserPermanentAdmin();
+ doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+ assertEquals(0, mCommand.exec(mBinder, in, out, err,
+ new String[]{"is-main-user-permanent-admin"}, mShellCallback, mResultReceiver));
+
+ mWriter.flush();
+ assertEquals("false", mOutStream.toString().trim());
+ }
+
+
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index d71deaf..f368a66 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -16,7 +16,6 @@
package com.android.server.power;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -30,8 +29,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.AdditionalMatchers.gt;
-import static org.mockito.AdditionalMatchers.leq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -81,6 +78,7 @@
import android.service.dreams.DreamManagerInternal;
import android.sysprop.PowerProperties;
import android.test.mock.MockContentResolver;
+import android.util.IntArray;
import android.view.Display;
import android.view.DisplayInfo;
@@ -153,9 +151,6 @@
@Mock
private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
- @Mock
- private ActivityManagerInternal mActivityManagerInternal;
-
private PowerManagerService mService;
private ContextWrapper mContextSpy;
private BatteryReceiver mBatteryReceiver;
@@ -211,7 +206,6 @@
addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock);
addLocalServiceMock(DreamManagerInternal.class, mDreamManagerInternalMock);
- addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternal);
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mResourcesSpy = spy(mContextSpy.getResources());
@@ -228,14 +222,6 @@
mClock = new OffsettableClock.Stopped();
mTestLooper = new TestLooper(mClock::now);
-
- // Set up canHoldWakeLocksInDeepDoze.
- // - procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> true
- // - procstate > PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> false
- when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
- anyInt(), leq(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(true);
- when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
- anyInt(), gt(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(false);
}
private PowerManagerService createService() {
@@ -2337,6 +2323,31 @@
verify(mLowPowerStandbyControllerMock).setActiveDuringMaintenance(false);
}
+ @Test
+ public void testPowerGroupInitialization_multipleDisplayGroups() {
+ IntArray displayGroupIds = IntArray.wrap(new int[]{1, 2, 3});
+ when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+ createService();
+ startSystem();
+
+ // Power group for DEFAULT_DISPLAY_GROUP is added by default.
+ assertThat(mService.getPowerGroupSize()).isEqualTo(4);
+ }
+
+ @Test
+ public void testPowerGroupInitialization_multipleDisplayGroupsWithDefaultGroup() {
+ IntArray displayGroupIds = IntArray.wrap(new int[]{Display.DEFAULT_DISPLAY_GROUP, 1, 2, 3});
+ when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+ createService();
+ startSystem();
+
+ // Power group for DEFAULT_DISPLAY_GROUP is added once even if getDisplayGroupIds() return
+ // an array including DEFAULT_DESIPLAY_GROUP.
+ assertThat(mService.getPowerGroupSize()).isEqualTo(4);
+ }
+
private WakeLock acquireWakeLock(String tag, int flags) {
IBinder token = new Binder();
String packageName = "pkg.name";
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 1ecd4a1..79f69ee 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -4131,17 +4131,26 @@
}
@Test
- public void testTooManyGroups() {
+ public void testTooManyGroups_fromTargetApp() {
+ testTooManyGroups(/* fromTargetApp= */ true);
+ }
+
+ @Test
+ public void testTooManyGroups_fromListener() {
+ testTooManyGroups(/* fromTargetApp= */ false);
+ }
+
+ private void testTooManyGroups(boolean fromTargetApp) {
for (int i = 0; i < NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; i++) {
NotificationChannelGroup group = new NotificationChannelGroup(String.valueOf(i),
String.valueOf(i));
- mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, fromTargetApp);
}
try {
NotificationChannelGroup group = new NotificationChannelGroup(
String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT),
String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT));
- mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, fromTargetApp);
fail("Allowed to create too many notification channel groups");
} catch (IllegalStateException e) {
// great
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 12f124e..6f6e2242 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -38,11 +38,12 @@
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
-import static com.android.os.AtomsProto.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ENABLED_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.UID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
import static junit.framework.Assert.assertEquals;
@@ -95,7 +96,6 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.Condition;
-import android.service.notification.DNDModeProto;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenPolicy;
@@ -898,7 +898,7 @@
assertEquals(n + 1, events.size());
for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
if (builder.getAtomId() == DND_MODE_RULE) {
- if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == DNDModeProto.ROOT_CONFIG) {
+ if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == ROOT_CONFIG) {
assertTrue(builder.getBoolean(ENABLED_FIELD_NUMBER));
assertFalse(builder.getBoolean(CHANNELS_BYPASSING_FIELD_NUMBER));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 3dcae91..0044e2e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -66,6 +66,7 @@
import android.view.Display;
import android.view.DisplayInfo;
import android.view.IDisplayWindowListener;
+import android.view.WindowManager;
import androidx.test.filters.MediumTest;
@@ -456,13 +457,15 @@
mAtm.mSupportsNonResizableMultiWindow = 0;
// Supports on large screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
assertTrue(activity.supportsMultiWindow());
assertTrue(task.supportsMultiWindow());
// Not supports on small screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
@@ -475,8 +478,10 @@
new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
// This is larger than the min dimensions device support in multi window,
// the activity will not be supported in multi window if the device respects
- /* minWidth= */(int) (mAtm.mLargeScreenSmallestScreenWidthDp * density),
- /* minHeight= */(int) (mAtm.mLargeScreenSmallestScreenWidthDp * density));
+ /* minWidth= */
+ (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP * density),
+ /* minHeight= */
+ (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP * density));
final ActivityRecord activity = new ActivityBuilder(mAtm)
.setCreateTask(true)
.setWindowLayout(windowLayout)
@@ -501,13 +506,15 @@
mAtm.mRespectsActivityMinWidthHeightMultiWindow = 0;
// Ignore on large screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
assertTrue(activity.supportsMultiWindow());
assertTrue(task.supportsMultiWindow());
// Check on small screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
@@ -518,7 +525,7 @@
// This is smaller than the min dimensions device support in multi window,
// the activity will be supported in multi window
final float density = mContext.getResources().getDisplayMetrics().density;
- final int supportedWidth = (int) (mAtm.mLargeScreenSmallestScreenWidthDp
+ final int supportedWidth = (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
* mAtm.mMinPercentageMultiWindowSupportWidth * density);
final ActivityInfo.WindowLayout windowLayout =
new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
@@ -531,15 +538,17 @@
.build();
final Task task = activity.getTask();
final TaskDisplayArea tda = task.getDisplayArea();
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
- tda.getConfiguration().screenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
+ tda.getConfiguration().screenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
tda.getConfiguration().orientation = ORIENTATION_LANDSCAPE;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
tda.getConfiguration().screenWidthDp = (int) Math.ceil(
- mAtm.mLargeScreenSmallestScreenWidthDp
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
/ mAtm.mMinPercentageMultiWindowSupportWidth);
assertTrue(activity.supportsMultiWindow());
@@ -551,7 +560,7 @@
// This is smaller than the min dimensions device support in multi window,
// the activity will be supported in multi window
final float density = mContext.getResources().getDisplayMetrics().density;
- final int supportedHeight = (int) (mAtm.mLargeScreenSmallestScreenWidthDp
+ final int supportedHeight = (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
* mAtm.mMinPercentageMultiWindowSupportHeight * density);
final ActivityInfo.WindowLayout windowLayout =
new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
@@ -564,15 +573,17 @@
.build();
final Task task = activity.getTask();
final TaskDisplayArea tda = task.getDisplayArea();
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
- tda.getConfiguration().screenHeightDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
+ tda.getConfiguration().screenHeightDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
tda.getConfiguration().orientation = ORIENTATION_PORTRAIT;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
tda.getConfiguration().screenHeightDp = (int) Math.ceil(
- mAtm.mLargeScreenSmallestScreenWidthDp
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
/ mAtm.mMinPercentageMultiWindowSupportHeight);
assertTrue(activity.supportsMultiWindow());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
index 8cc362c..17f6d51a7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
@@ -35,6 +35,8 @@
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
+import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
@@ -45,6 +47,7 @@
import android.provider.DeviceConfig;
import android.util.DisplayMetrics;
import android.view.ContentRecordingSession;
+import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -258,8 +261,17 @@
@Test
public void testOnTaskBoundsConfigurationChanged_notifiesCallback() {
+ mTask.getRootTask().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
+
final int recordedWidth = 333;
final int recordedHeight = 999;
+
+ final ActivityInfo info = new ActivityInfo();
+ info.windowLayout = new ActivityInfo.WindowLayout(-1 /* width */,
+ -1 /* widthFraction */, -1 /* height */, -1 /* heightFraction */,
+ Gravity.NO_GRAVITY, recordedWidth, recordedHeight);
+ mTask.setMinDimensions(info);
+
// WHEN a recording is ongoing.
mContentRecorder.setContentRecordingSession(mTaskSession);
mContentRecorder.updateRecording();
@@ -267,7 +279,6 @@
// WHEN a configuration change arrives, and the recorded content is a different size.
mTask.setBounds(new Rect(0, 0, recordedWidth, recordedHeight));
- mContentRecorder.onConfigurationChanged(mDefaultDisplay.getLastOrientation());
assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
// THEN content in the captured DisplayArea is scaled to fit the surface size.
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index d242a5f..abbd397 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -117,6 +117,8 @@
import org.mockito.ArgumentCaptor;
import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
/**
* Tests for Size Compatibility mode.
@@ -172,6 +174,156 @@
}
@Test
+ public void testHorizontalReachabilityEnabledForTranslucentActivities() {
+ setUpDisplaySizeWithApp(2500, 1000);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+ config.setTranslucentLetterboxingOverrideEnabled(true);
+ config.setLetterboxHorizontalPositionMultiplier(0.5f);
+ config.setIsHorizontalReachabilityEnabled(true);
+
+ // Opaque activity
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+ addWindowToActivity(mActivity);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+
+ // Translucent Activity
+ final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+ .setLaunchedFromUid(mActivity.getUid())
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .build();
+ doReturn(false).when(translucentActivity).fillsParent();
+ mTask.addChild(translucentActivity);
+
+ spyOn(translucentActivity.mLetterboxUiController);
+ doReturn(true).when(translucentActivity.mLetterboxUiController)
+ .shouldShowLetterboxUi(any());
+
+ addWindowToActivity(translucentActivity);
+ translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+ final Function<ActivityRecord, Rect> innerBoundsOf =
+ (ActivityRecord a) -> {
+ final Rect bounds = new Rect();
+ a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+ return bounds;
+ };
+ final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+ innerBoundsOf.apply(translucentActivity));
+ final Runnable checkIsLeft = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).left).isEqualTo(0);
+ final Runnable checkIsRight = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).right).isEqualTo(2500);
+ final Runnable checkIsCentered = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).left > 0
+ && innerBoundsOf.apply(translucentActivity).right < 2500).isTrue();
+
+ final Consumer<Integer> doubleClick =
+ (Integer x) -> {
+ mActivity.mLetterboxUiController.handleHorizontalDoubleTap(x);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+ };
+
+ // Initial state
+ checkIsCentered.run();
+
+ // Double-click left
+ doubleClick.accept(/* x */ 10);
+ checkLetterboxPositions.run();
+ checkIsLeft.run();
+
+ // Double-click right
+ doubleClick.accept(/* x */ 1990);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+
+ // Double-click right
+ doubleClick.accept(/* x */ 1990);
+ checkLetterboxPositions.run();
+ checkIsRight.run();
+
+ // Double-click left
+ doubleClick.accept(/* x */ 10);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+ }
+
+ @Test
+ public void testVerticalReachabilityEnabledForTranslucentActivities() {
+ setUpDisplaySizeWithApp(1000, 2500);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+ config.setTranslucentLetterboxingOverrideEnabled(true);
+ config.setLetterboxVerticalPositionMultiplier(0.5f);
+ config.setIsVerticalReachabilityEnabled(true);
+
+ // Opaque activity
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+ addWindowToActivity(mActivity);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+
+ // Translucent Activity
+ final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+ .setLaunchedFromUid(mActivity.getUid())
+ .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
+ .build();
+ doReturn(false).when(translucentActivity).fillsParent();
+ mTask.addChild(translucentActivity);
+
+ spyOn(translucentActivity.mLetterboxUiController);
+ doReturn(true).when(translucentActivity.mLetterboxUiController)
+ .shouldShowLetterboxUi(any());
+
+ addWindowToActivity(translucentActivity);
+ translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+ final Function<ActivityRecord, Rect> innerBoundsOf =
+ (ActivityRecord a) -> {
+ final Rect bounds = new Rect();
+ a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+ return bounds;
+ };
+ final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+ innerBoundsOf.apply(translucentActivity));
+ final Runnable checkIsTop = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).top).isEqualTo(0);
+ final Runnable checkIsBottom = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).bottom).isEqualTo(2500);
+ final Runnable checkIsCentered = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).top > 0
+ && innerBoundsOf.apply(translucentActivity).bottom < 2500).isTrue();
+
+ final Consumer<Integer> doubleClick =
+ (Integer y) -> {
+ mActivity.mLetterboxUiController.handleVerticalDoubleTap(y);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+ };
+
+ // Initial state
+ checkIsCentered.run();
+
+ // Double-click top
+ doubleClick.accept(/* y */ 10);
+ checkLetterboxPositions.run();
+ checkIsTop.run();
+
+ // Double-click bottom
+ doubleClick.accept(/* y */ 1990);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+
+ // Double-click bottom
+ doubleClick.accept(/* y */ 1990);
+ checkLetterboxPositions.run();
+ checkIsBottom.run();
+
+ // Double-click top
+ doubleClick.accept(/* y */ 10);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+ }
+
+ @Test
public void testApplyStrategyToTranslucentActivities() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2000, 1000);
@@ -822,7 +974,7 @@
.setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
.setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.build();
- assertFalse(activity.shouldCreateCompatDisplayInsets());
+ assertTrue(activity.shouldCreateCompatDisplayInsets());
// The non-resizable activity should not be size compat because it is on a resizable task
// in multi-window mode.
@@ -855,7 +1007,7 @@
}
@Test
- public void testShouldNotCreateCompatDisplayInsetsWhenRootActivityIsResizeable() {
+ public void testShouldCreateCompatDisplayInsetsWhenUnresizeableAndSupportsSizeChangesFalse() {
setUpDisplaySizeWithApp(1000, 2500);
// Make the task root resizable.
@@ -864,7 +1016,7 @@
// Create an activity on the same task.
final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- assertFalse(activity.shouldCreateCompatDisplayInsets());
+ assertTrue(activity.shouldCreateCompatDisplayInsets());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index f4a266c..013c6d5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -545,7 +545,6 @@
mDevEnableNonResizableMultiWindow = false;
mMinPercentageMultiWindowSupportHeight = 0.3f;
mMinPercentageMultiWindowSupportWidth = 0.5f;
- mLargeScreenSmallestScreenWidthDp = 600;
mSupportsNonResizableMultiWindow = 0;
mRespectsActivityMinWidthHeightMultiWindow = 0;
mForceResizableActivities = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 9cd80a3..5208e5a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -535,6 +535,34 @@
assertEquals(reqBounds.height(), task.getBounds().height());
}
+ /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
+ @Test
+ public void testBoundsOnModeChangeFreeformToFullscreen() {
+ DisplayContent display = mAtm.mRootWindowContainer.getDefaultDisplay();
+ Task rootTask = new TaskBuilder(mSupervisor).setDisplay(display).setCreateActivity(true)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ Task task = rootTask.getBottomMostTask();
+ task.getRootActivity().setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
+ DisplayInfo info = new DisplayInfo();
+ display.mDisplay.getDisplayInfo(info);
+ final Rect fullScreenBounds = new Rect(0, 0, info.logicalWidth, info.logicalHeight);
+ final Rect freeformBounds = new Rect(fullScreenBounds);
+ freeformBounds.inset((int) (freeformBounds.width() * 0.2),
+ (int) (freeformBounds.height() * 0.2));
+ task.setBounds(freeformBounds);
+
+ assertEquals(freeformBounds, task.getBounds());
+
+ // FULLSCREEN inherits bounds
+ rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ assertEquals(fullScreenBounds, task.getBounds());
+ assertEquals(freeformBounds, task.mLastNonFullscreenBounds);
+
+ // FREEFORM restores bounds
+ rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ assertEquals(freeformBounds, task.getBounds());
+ }
+
/**
* Tests that a task with forced orientation has orientation-consistent bounds within the
* parent.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index fec079b..7e4a9de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -30,6 +30,9 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -39,6 +42,7 @@
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.util.DisplayMetrics;
+import android.util.TypedValue;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
@@ -47,6 +51,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
class TestDisplayContent extends DisplayContent {
@@ -197,10 +203,21 @@
MockitoAnnotations.initMocks(this);
doReturn(mMockContext).when(mService.mContext).createConfigurationContext(any());
doReturn(mResources).when(mMockContext).getResources();
- doReturn(valueDp * mDisplayMetrics.density)
- .when(mResources)
- .getDimension(
- com.android.internal.R.dimen.default_minimal_size_resizable_task);
+ doAnswer(
+ new Answer() {
+ @Override
+ public Object answer(InvocationOnMock i) {
+ Object[] args = i.getArguments();
+ TypedValue v = (TypedValue) args[1];
+ v.type = TypedValue.TYPE_DIMENSION;
+ v.data = TypedValue.createComplexDimension(valueDp,
+ TypedValue.COMPLEX_UNIT_DIP);
+ return null;
+ }
+ }
+ ).when(mResources).getValue(
+ eq(com.android.internal.R.dimen.default_minimal_size_resizable_task),
+ any(TypedValue.class), eq(true));
return this;
}
Builder setDeviceStateController(@NonNull DeviceStateController deviceStateController) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 3f14217..048e2cc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
@@ -1376,6 +1377,9 @@
enteringAnimReports.clear();
closeTransition.finishTransition();
+ assertEquals(ActivityTaskManagerService.APP_SWITCH_DISALLOW, mAtm.getBalAppSwitchesState());
+ assertFalse(activity1.app.hasActivityInVisibleTask());
+
verify(snapshotController, times(1)).recordSnapshot(eq(task1), eq(false));
assertTrue(enteringAnimReports.contains(activity2));
}
@@ -1696,7 +1700,8 @@
@Test
public void testTransitionVisibleChange() {
registerTestTransitionPlayer();
- final ActivityRecord app = createActivityRecord(mDisplayContent);
+ final ActivityRecord app = createActivityRecord(
+ mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
final Transition transition = new Transition(TRANSIT_OPEN, 0 /* flags */,
app.mTransitionController, mWm.mSyncEngine);
app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
@@ -1746,7 +1751,8 @@
@Test
public void testVisibleChange_snapshot() {
registerTestTransitionPlayer();
- final ActivityRecord app = createActivityRecord(mDisplayContent);
+ final ActivityRecord app = createActivityRecord(
+ mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */,
app.mTransitionController, mWm.mSyncEngine);
app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING
index 1c0c71b..a3fe6f2 100644
--- a/services/usage/java/com/android/server/usage/TEST_MAPPING
+++ b/services/usage/java/com/android/server/usage/TEST_MAPPING
@@ -18,9 +18,7 @@
"exclude-filter": "com.android.server.usage.StorageStatsServiceTest"
}
]
- }
- ],
- "presubmit-large": [
+ },
{
"name": "CtsUsageStatsTestCases",
"options": [
diff --git a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
index 0dcf8ce..b1cd994 100644
--- a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.usb.UsbConfiguration;
-import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
@@ -35,9 +34,12 @@
import android.service.usb.UsbDirectMidiDeviceProto;
import android.util.Log;
+import com.android.internal.midi.MidiEventMultiScheduler;
import com.android.internal.midi.MidiEventScheduler;
import com.android.internal.midi.MidiEventScheduler.MidiEvent;
import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.server.usb.descriptors.UsbACMidi10Endpoint;
+import com.android.server.usb.descriptors.UsbDescriptor;
import com.android.server.usb.descriptors.UsbDescriptorParser;
import com.android.server.usb.descriptors.UsbEndpointDescriptor;
import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
@@ -45,6 +47,7 @@
import libcore.io.IoUtils;
+import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -56,7 +59,7 @@
*/
public final class UsbDirectMidiDevice implements Closeable {
private static final String TAG = "UsbDirectMidiDevice";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
private Context mContext;
private String mName;
@@ -74,9 +77,6 @@
private MidiDeviceServer mServer;
- // event schedulers for each input port of the physical device
- private MidiEventScheduler[] mEventSchedulers;
-
// Timeout for sending a packet to a device.
// If bulkTransfer times out, retry sending the packet up to 20 times.
private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 50;
@@ -86,8 +86,21 @@
private static final int THREAD_JOIN_TIMEOUT_MILLISECONDS = 200;
private ArrayList<UsbDeviceConnection> mUsbDeviceConnections;
+
+ // Array of endpoints by device connection.
private ArrayList<ArrayList<UsbEndpoint>> mInputUsbEndpoints;
private ArrayList<ArrayList<UsbEndpoint>> mOutputUsbEndpoints;
+
+ // Array of cable counts by device connection.
+ // Each number here maps to an entry in mInputUsbEndpoints or mOutputUsbEndpoints.
+ // This is needed because this info is part of UsbEndpointDescriptor but not UsbEndpoint.
+ private ArrayList<ArrayList<Integer>> mInputUsbEndpointCableCounts;
+ private ArrayList<ArrayList<Integer>> mOutputUsbEndpointCableCounts;
+
+ // Array of event schedulers by device connection.
+ // Each number here maps to an entry in mOutputUsbEndpoints.
+ private ArrayList<ArrayList<MidiEventMultiScheduler>> mMidiEventMultiSchedulers;
+
private ArrayList<Thread> mThreads;
private UsbMidiBlockParser mMidiBlockParser = new UsbMidiBlockParser();
@@ -97,8 +110,6 @@
private boolean mIsOpen;
private boolean mServerAvailable;
- private UsbMidiPacketConverter mUsbMidiPacketConverter;
-
private PowerBoostSetter mPowerBoostSetter = null;
private static final byte MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE = 0x02;
@@ -238,9 +249,9 @@
interfaceDescriptor.getEndpointDescriptor(endpointIndex);
// 0 is output, 1 << 7 is input.
if (endpoint.getDirection() == 0) {
- numOutputs++;
+ numOutputs += getNumJacks(endpoint);
} else {
- numInputs++;
+ numInputs += getNumJacks(endpoint);
}
}
}
@@ -307,19 +318,21 @@
Log.d(TAG, "openLocked()");
UsbManager manager = mContext.getSystemService(UsbManager.class);
- // Converting from raw MIDI to USB MIDI is not thread-safe.
- // UsbMidiPacketConverter creates a converter from raw MIDI
- // to USB MIDI for each USB output.
- mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
-
mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>();
mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
+ mInputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+ mOutputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+ mMidiEventMultiSchedulers = new ArrayList<ArrayList<MidiEventMultiScheduler>>();
mThreads = new ArrayList<Thread>();
for (int interfaceIndex = 0; interfaceIndex < mUsbInterfaces.size(); interfaceIndex++) {
ArrayList<UsbEndpoint> inputEndpoints = new ArrayList<UsbEndpoint>();
ArrayList<UsbEndpoint> outputEndpoints = new ArrayList<UsbEndpoint>();
+ ArrayList<Integer> inputEndpointCableCounts = new ArrayList<Integer>();
+ ArrayList<Integer> outputEndpointCableCounts = new ArrayList<Integer>();
+ ArrayList<MidiEventMultiScheduler> midiEventMultiSchedulers =
+ new ArrayList<MidiEventMultiScheduler>();
UsbInterfaceDescriptor interfaceDescriptor = mUsbInterfaces.get(interfaceIndex);
for (int endpointIndex = 0; endpointIndex < interfaceDescriptor.getNumEndpoints();
endpointIndex++) {
@@ -328,8 +341,13 @@
// 0 is output, 1 << 7 is input.
if (endpoint.getDirection() == 0) {
outputEndpoints.add(endpoint.toAndroid(mParser));
+ outputEndpointCableCounts.add(getNumJacks(endpoint));
+ MidiEventMultiScheduler scheduler =
+ new MidiEventMultiScheduler(getNumJacks(endpoint));
+ midiEventMultiSchedulers.add(scheduler);
} else {
inputEndpoints.add(endpoint.toAndroid(mParser));
+ inputEndpointCableCounts.add(getNumJacks(endpoint));
}
}
if (!outputEndpoints.isEmpty() || !inputEndpoints.isEmpty()) {
@@ -341,40 +359,69 @@
mUsbDeviceConnections.add(connection);
mInputUsbEndpoints.add(inputEndpoints);
mOutputUsbEndpoints.add(outputEndpoints);
+ mInputUsbEndpointCableCounts.add(inputEndpointCableCounts);
+ mOutputUsbEndpointCableCounts.add(outputEndpointCableCounts);
+ mMidiEventMultiSchedulers.add(midiEventMultiSchedulers);
}
}
- mEventSchedulers = new MidiEventScheduler[mNumOutputs];
-
- for (int i = 0; i < mNumOutputs; i++) {
- MidiEventScheduler scheduler = new MidiEventScheduler();
- mEventSchedulers[i] = scheduler;
- mMidiInputPortReceivers[i].setReceiver(scheduler.getReceiver());
+ // Set up event schedulers
+ int outputIndex = 0;
+ for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+ connectionIndex++) {
+ for (int endpointIndex = 0;
+ endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+ endpointIndex++) {
+ int cableCount =
+ mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+ MidiEventMultiScheduler multiScheduler =
+ mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+ for (int cableNumber = 0; cableNumber < cableCount; cableNumber++) {
+ MidiEventScheduler scheduler = multiScheduler.getEventScheduler(cableNumber);
+ mMidiInputPortReceivers[outputIndex].setReceiver(scheduler.getReceiver());
+ outputIndex++;
+ }
+ }
}
final MidiReceiver[] outputReceivers = mServer.getOutputPortReceivers();
// Create input thread for each input port of the physical device
- int portNumber = 0;
+ int portStartNumber = 0;
for (int connectionIndex = 0; connectionIndex < mInputUsbEndpoints.size();
connectionIndex++) {
for (int endpointIndex = 0;
endpointIndex < mInputUsbEndpoints.get(connectionIndex).size();
endpointIndex++) {
+ // Each USB endpoint maps to one or more outputReceivers. USB MIDI data from an
+ // endpoint should be sent to the appropriate outputReceiver. A new thread is
+ // created and waits for incoming USB data. Once the data is received, it is added
+ // to the packet converter. The packet converter acts as an inverse multiplexer.
+ // With a for loop, data is pulled per cable and sent to the correct output
+ // receiver. The first byte of each legacy MIDI 1.0 USB message indicates which
+ // cable the data should be used and is how the reverse multiplexer directs data.
+ // For MIDI UMP endpoints, a multiplexer is not needed as we are just swapping
+ // the endianness of the packets.
final UsbDeviceConnection connectionFinal =
mUsbDeviceConnections.get(connectionIndex);
final UsbEndpoint endpointFinal =
mInputUsbEndpoints.get(connectionIndex).get(endpointIndex);
- final int portFinal = portNumber;
+ final int portStartFinal = portStartNumber;
+ final int cableCountFinal =
+ mInputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
- Thread newThread = new Thread("UsbDirectMidiDevice input thread " + portFinal) {
+ Thread newThread = new Thread("UsbDirectMidiDevice input thread "
+ + portStartFinal) {
@Override
public void run() {
final UsbRequest request = new UsbRequest();
+ final UsbMidiPacketConverter packetConverter = new UsbMidiPacketConverter();
+ packetConverter.createDecoders(cableCountFinal);
try {
request.initialize(connectionFinal, endpointFinal);
byte[] inputBuffer = new byte[endpointFinal.getMaxPacketSize()];
- while (true) {
+ boolean keepGoing = true;
+ while (keepGoing) {
if (Thread.currentThread().interrupted()) {
Log.w(TAG, "input thread interrupted");
break;
@@ -404,42 +451,56 @@
logByteArray("Input before conversion ", inputBuffer,
0, bytesRead);
}
+
+ // Add packets into the packet decoder.
+ if (!mIsUniversalMidiDevice) {
+ packetConverter.decodeMidiPackets(inputBuffer, bytesRead);
+ }
+
byte[] convertedArray;
- if (mIsUniversalMidiDevice) {
- // For USB, each 32 bit word of a UMP is
- // sent with the least significant byte first.
- convertedArray = swapEndiannessPerWord(inputBuffer,
- bytesRead);
- } else {
- if (mUsbMidiPacketConverter == null) {
- Log.w(TAG, "mUsbMidiPacketConverter is null");
+ for (int cableNumber = 0; cableNumber < cableCountFinal;
+ cableNumber++) {
+ if (mIsUniversalMidiDevice) {
+ // For USB, each 32 bit word of a UMP is
+ // sent with the least significant byte first.
+ convertedArray = swapEndiannessPerWord(inputBuffer,
+ bytesRead);
+ } else {
+ convertedArray =
+ packetConverter.pullDecodedMidiPackets(
+ cableNumber);
+ }
+
+ if (DEBUG) {
+ logByteArray("Input " + cableNumber
+ + " after conversion ", convertedArray, 0,
+ convertedArray.length);
+ }
+
+ if (convertedArray.length == 0) {
+ continue;
+ }
+
+ if ((outputReceivers == null)
+ || (outputReceivers[portStartFinal + cableNumber]
+ == null)) {
+ Log.w(TAG, "outputReceivers is null");
+ keepGoing = false;
break;
}
- convertedArray =
- mUsbMidiPacketConverter.usbMidiToRawMidi(
- inputBuffer, bytesRead);
- }
+ outputReceivers[portStartFinal + cableNumber].send(
+ convertedArray, 0, convertedArray.length,
+ timestamp);
- if (DEBUG) {
- logByteArray("Input after conversion ", convertedArray,
- 0, convertedArray.length);
- }
-
- if ((outputReceivers == null)
- || (outputReceivers[portFinal] == null)) {
- Log.w(TAG, "outputReceivers is null");
- break;
- }
- outputReceivers[portFinal].send(convertedArray, 0,
- convertedArray.length, timestamp);
-
- // Boost power if there seems to be a voice message.
- // For legacy devices, boost when message is more than size 1.
- // For UMP devices, boost for channel voice messages.
- if ((mPowerBoostSetter != null && convertedArray.length > 1)
- && (!mIsUniversalMidiDevice
- || isChannelVoiceMessage(convertedArray))) {
- mPowerBoostSetter.boostPower();
+ // Boost power if there seems to be a voice message.
+ // For legacy devices, boost if message length > 1.
+ // For UMP devices, boost for channel voice messages.
+ if ((mPowerBoostSetter != null
+ && convertedArray.length > 1)
+ && (!mIsUniversalMidiDevice
+ || isChannelVoiceMessage(convertedArray))) {
+ mPowerBoostSetter.boostPower();
+ }
}
}
}
@@ -455,64 +516,93 @@
};
newThread.start();
mThreads.add(newThread);
- portNumber++;
+ portStartNumber += cableCountFinal;
}
}
// Create output thread for each output port of the physical device
- portNumber = 0;
+ portStartNumber = 0;
for (int connectionIndex = 0; connectionIndex < mOutputUsbEndpoints.size();
connectionIndex++) {
for (int endpointIndex = 0;
endpointIndex < mOutputUsbEndpoints.get(connectionIndex).size();
endpointIndex++) {
+ // Each USB endpoint maps to one or more MIDI ports. Each port has an event
+ // scheduler that is used to pull incoming raw MIDI bytes from Android apps.
+ // With a MidiEventMultiScheduler, data can be pulled if any of the schedulers
+ // have new incoming data. This data is then packaged as USB MIDI packets before
+ // getting sent through USB. One thread will be created per endpoint that pulls
+ // data from all relevant event schedulers. Raw MIDI from the event schedulers
+ // will be converted to the correct USB MIDI format before getting sent through
+ // USB.
+
final UsbDeviceConnection connectionFinal =
mUsbDeviceConnections.get(connectionIndex);
final UsbEndpoint endpointFinal =
mOutputUsbEndpoints.get(connectionIndex).get(endpointIndex);
- final int portFinal = portNumber;
- final MidiEventScheduler eventSchedulerFinal = mEventSchedulers[portFinal];
+ final int portStartFinal = portStartNumber;
+ final int cableCountFinal =
+ mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+ final MidiEventMultiScheduler multiSchedulerFinal =
+ mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
- Thread newThread = new Thread("UsbDirectMidiDevice output thread " + portFinal) {
+ Thread newThread = new Thread("UsbDirectMidiDevice output write thread "
+ + portStartFinal) {
@Override
public void run() {
try {
- while (true) {
- if (Thread.currentThread().interrupted()) {
- Log.w(TAG, "output thread interrupted");
+ final ByteArrayOutputStream midi2ByteStream =
+ new ByteArrayOutputStream();
+ final UsbMidiPacketConverter packetConverter =
+ new UsbMidiPacketConverter();
+ packetConverter.createEncoders(cableCountFinal);
+ boolean isInterrupted = false;
+ while (!isInterrupted) {
+ boolean wasSuccessful = multiSchedulerFinal.waitNextEvent();
+ if (!wasSuccessful) {
+ Log.d(TAG, "output thread closed");
break;
}
- MidiEvent event;
- try {
- event = (MidiEvent) eventSchedulerFinal.waitNextEvent();
- } catch (InterruptedException e) {
- Log.w(TAG, "event scheduler interrupted");
- break;
- }
- if (event == null) {
- Log.w(TAG, "event is null");
- break;
- }
-
- if (DEBUG) {
- logByteArray("Output before conversion ", event.data, 0,
- event.count);
- }
-
- byte[] convertedArray;
- if (mIsUniversalMidiDevice) {
- // For USB, each 32 bit word of a UMP is
- // sent with the least significant byte first.
- convertedArray = swapEndiannessPerWord(event.data,
- event.count);
- } else {
- if (mUsbMidiPacketConverter == null) {
- Log.w(TAG, "mUsbMidiPacketConverter is null");
- break;
+ long now = System.nanoTime();
+ for (int cableNumber = 0; cableNumber < cableCountFinal;
+ cableNumber++) {
+ MidiEventScheduler eventScheduler =
+ multiSchedulerFinal.getEventScheduler(cableNumber);
+ MidiEvent event =
+ (MidiEvent) eventScheduler.getNextEvent(now);
+ while (event != null) {
+ if (DEBUG) {
+ logByteArray("Output before conversion ",
+ event.data, 0, event.count);
+ }
+ if (mIsUniversalMidiDevice) {
+ // For USB, each 32 bit word of a UMP is
+ // sent with the least significant byte first.
+ byte[] convertedArray = swapEndiannessPerWord(
+ event.data, event.count);
+ midi2ByteStream.write(convertedArray, 0,
+ convertedArray.length);
+ } else {
+ packetConverter.encodeMidiPackets(event.data,
+ event.count, cableNumber);
+ }
+ eventScheduler.addEventToPool(event);
+ event = (MidiEvent) eventScheduler.getNextEvent(now);
}
+ }
+
+ if (Thread.currentThread().interrupted()) {
+ Log.d(TAG, "output thread interrupted");
+ break;
+ }
+
+ byte[] convertedArray = new byte[0];
+ if (mIsUniversalMidiDevice) {
+ convertedArray = midi2ByteStream.toByteArray();
+ midi2ByteStream.reset();
+ } else {
convertedArray =
- mUsbMidiPacketConverter.rawMidiToUsbMidi(
- event.data, event.count, portFinal);
+ packetConverter.pullEncodedMidiPackets();
}
if (DEBUG) {
@@ -520,7 +610,6 @@
convertedArray.length);
}
- boolean isInterrupted = false;
// Split the packet into multiple if they are greater than the
// endpoint's max packet size.
for (int curPacketStart = 0;
@@ -558,11 +647,9 @@
}
}
}
- if (isInterrupted == true) {
- break;
- }
- eventSchedulerFinal.addEventToPool(event);
}
+ } catch (InterruptedException e) {
+ Log.w(TAG, "output thread: ", e);
} catch (NullPointerException e) {
Log.e(TAG, "output thread: ", e);
}
@@ -571,7 +658,7 @@
};
newThread.start();
mThreads.add(newThread);
- portNumber++;
+ portStartNumber += cableCountFinal;
}
}
@@ -667,11 +754,21 @@
}
mThreads = null;
- for (int i = 0; i < mEventSchedulers.length; i++) {
+ for (int i = 0; i < mMidiInputPortReceivers.length; i++) {
mMidiInputPortReceivers[i].setReceiver(null);
- mEventSchedulers[i].close();
}
- mEventSchedulers = null;
+
+ for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+ connectionIndex++) {
+ for (int endpointIndex = 0;
+ endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+ endpointIndex++) {
+ MidiEventMultiScheduler multiScheduler =
+ mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+ multiScheduler.close();
+ }
+ }
+ mMidiEventMultiSchedulers = null;
for (UsbDeviceConnection connection : mUsbDeviceConnections) {
connection.close();
@@ -679,8 +776,8 @@
mUsbDeviceConnections = null;
mInputUsbEndpoints = null;
mOutputUsbEndpoints = null;
-
- mUsbMidiPacketConverter = null;
+ mInputUsbEndpointCableCounts = null;
+ mOutputUsbEndpointCableCounts = null;
mIsOpen = false;
}
@@ -788,4 +885,19 @@
return messageType == MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE
|| messageType == MESSAGE_TYPE_MIDI_2_CHANNEL_VOICE;
}
+
+ // Returns the number of jacks for MIDI 1.0 endpoints.
+ // For MIDI 2.0 endpoints, this concept does not exist and each endpoint should be treated as
+ // one port.
+ private int getNumJacks(UsbEndpointDescriptor usbEndpointDescriptor) {
+ UsbDescriptor classSpecificEndpointDescriptor =
+ usbEndpointDescriptor.getClassSpecificEndpointDescriptor();
+ if (classSpecificEndpointDescriptor != null
+ && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) {
+ UsbACMidi10Endpoint midiEndpoint =
+ (UsbACMidi10Endpoint) classSpecificEndpointDescriptor;
+ return midiEndpoint.getNumJacks();
+ }
+ return 1;
+ }
}
diff --git a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
index 56bb236..65d7a41 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
@@ -16,12 +16,17 @@
package com.android.server.usb;
+import android.util.Log;
+
import java.io.ByteArrayOutputStream;
/**
- * Converts between MIDI packets and USB MIDI 1.0 packets.
+ * Converts between raw MIDI packets and USB MIDI 1.0 packets.
+ * This is NOT thread-safe. Please handle locking outside this function for multiple threads.
+ * For data mapping to an invalid cable number, this converter will use the first cable.
*/
public class UsbMidiPacketConverter {
+ private static final String TAG = "UsbMidiPacketConverter";
// Refer to Table 4-1 in USB MIDI 1.0 spec.
private static final int[] PAYLOAD_SIZE = new int[]{
@@ -74,54 +79,133 @@
private static final byte SYSEX_START_EXCLUSIVE = (byte) 0xF0;
private static final byte SYSEX_END_EXCLUSIVE = (byte) 0xF7;
- private UsbMidiDecoder mUsbMidiDecoder = new UsbMidiDecoder();
private UsbMidiEncoder[] mUsbMidiEncoders;
+ private ByteArrayOutputStream mEncoderOutputStream = new ByteArrayOutputStream();
- public UsbMidiPacketConverter(int numEncoders) {
- mUsbMidiEncoders = new UsbMidiEncoder[numEncoders];
- for (int i = 0; i < numEncoders; i++) {
- mUsbMidiEncoders[i] = new UsbMidiEncoder();
- }
- }
+ private UsbMidiDecoder mUsbMidiDecoder;
/**
- * Converts a USB MIDI array into a raw MIDI array.
+ * Creates encoders.
*
- * @param usbMidiBytes the USB MIDI bytes to convert
- * @param size the size of usbMidiBytes
- * @return byte array of raw MIDI packets
+ * createEncoders() must be called before raw MIDI can be converted to USB MIDI.
+ *
+ * @param size the number of encoders to create
*/
- public byte[] usbMidiToRawMidi(byte[] usbMidiBytes, int size) {
- return mUsbMidiDecoder.decode(usbMidiBytes, size);
+ public void createEncoders(int size) {
+ mUsbMidiEncoders = new UsbMidiEncoder[size];
+ for (int i = 0; i < size; i++) {
+ mUsbMidiEncoders[i] = new UsbMidiEncoder(i);
+ }
}
/**
* Converts a raw MIDI array into a USB MIDI array.
*
+ * Call pullEncodedMidiPackets to retrieve the byte array.
+ *
* @param midiBytes the raw MIDI bytes to convert
* @param size the size of usbMidiBytes
* @param encoderId which encoder to use
+ */
+ public void encodeMidiPackets(byte[] midiBytes, int size, int encoderId) {
+ // Use the first encoder if the encoderId is invalid.
+ if (encoderId >= mUsbMidiEncoders.length) {
+ Log.w(TAG, "encoderId " + encoderId + " invalid");
+ encoderId = 0;
+ }
+ byte[] encodedPacket = mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+ mEncoderOutputStream.write(encodedPacket, 0, encodedPacket.length);
+ }
+
+ /**
+ * Returns the encoded MIDI packets from encodeMidiPackets
+ *
* @return byte array of USB MIDI packets
*/
- public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size, int encoderId) {
- return mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+ public byte[] pullEncodedMidiPackets() {
+ byte[] output = mEncoderOutputStream.toByteArray();
+ mEncoderOutputStream.reset();
+ return output;
+ }
+
+ /**
+ * Creates decoders.
+ *
+ * createDecoders() must be called before USB MIDI can be converted to raw MIDI.
+ *
+ * @param size the number of decoders to create
+ */
+ public void createDecoders(int size) {
+ mUsbMidiDecoder = new UsbMidiDecoder(size);
+ }
+
+ /**
+ * Converts a USB MIDI array into a multiple MIDI arrays, one per cable.
+ *
+ * Call pullDecodedMidiPackets to retrieve the byte array.
+ *
+ * @param usbMidiBytes the USB MIDI bytes to convert
+ * @param size the size of usbMidiBytes
+ */
+ public void decodeMidiPackets(byte[] usbMidiBytes, int size) {
+ mUsbMidiDecoder.decode(usbMidiBytes, size);
+ }
+
+ /**
+ * Returns the decoded MIDI packets from decodeMidiPackets
+ *
+ * @param cableNumber the cable to pull data from
+ * @return byte array of raw MIDI packets
+ */
+ public byte[] pullDecodedMidiPackets(int cableNumber) {
+ return mUsbMidiDecoder.pullBytes(cableNumber);
}
private class UsbMidiDecoder {
+ int mNumJacks;
+ ByteArrayOutputStream[] mDecodedByteArrays;
+
+ UsbMidiDecoder(int numJacks) {
+ mNumJacks = numJacks;
+ mDecodedByteArrays = new ByteArrayOutputStream[numJacks];
+ for (int i = 0; i < numJacks; i++) {
+ mDecodedByteArrays[i] = new ByteArrayOutputStream();
+ }
+ }
+
// Decodes the data from USB MIDI to raw MIDI.
// Each valid 4 byte input maps to a 1-3 byte output.
// Reference the USB MIDI 1.0 spec for more info.
- public byte[] decode(byte[] usbMidiBytes, int size) {
+ public void decode(byte[] usbMidiBytes, int size) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ if (size % 4 != 0) {
+ Log.w(TAG, "size " + size + " not multiple of 4");
+ }
for (int i = 0; i + 3 < size; i += 4) {
+ int cableNumber = (usbMidiBytes[i] >> 4) & 0x0f;
int codeIndex = usbMidiBytes[i] & 0x0f;
int numPayloadBytes = PAYLOAD_SIZE[codeIndex];
if (numPayloadBytes < 0) {
continue;
}
- outputStream.write(usbMidiBytes, i + 1, numPayloadBytes);
+ // Use the first cable if the cable number is invalid.
+ if (cableNumber >= mNumJacks) {
+ Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+ cableNumber = 0;
+ }
+ mDecodedByteArrays[cableNumber].write(usbMidiBytes, i + 1, numPayloadBytes);
}
- return outputStream.toByteArray();
+ }
+
+ public byte[] pullBytes(int cableNumber) {
+ // Use the first cable if the cable number is invalid.
+ if (cableNumber >= mNumJacks) {
+ Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+ cableNumber = 0;
+ }
+ byte[] output = mDecodedByteArrays[cableNumber].toByteArray();
+ mDecodedByteArrays[cableNumber].reset();
+ return output;
}
}
@@ -135,6 +219,13 @@
private byte[] mEmptyBytes = new byte[3]; // Used to fill out extra data
+ private byte mShiftedCableNumber;
+
+ UsbMidiEncoder(int cableNumber) {
+ // Jack Id is always the left nibble of every byte so shift this now.
+ mShiftedCableNumber = (byte) (cableNumber << 4);
+ }
+
// Encodes the data from raw MIDI to USB MIDI.
// Each valid 1-3 byte input maps to a 4 byte output.
// Reference the USB MIDI 1.0 spec for more info.
@@ -153,7 +244,8 @@
midiBytes[curLocation];
mNumStoredSystemExclusiveBytes++;
if (mNumStoredSystemExclusiveBytes == 3) {
- outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES);
+ outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES
+ | mShiftedCableNumber);
outputStream.write(mStoredSystemExclusiveBytes, 0, 3);
mNumStoredSystemExclusiveBytes = 0;
}
@@ -179,7 +271,7 @@
byte codeIndexNumber = (byte) ((midiBytes[curLocation] >> 4) & 0x0f);
int channelMessageSize = PAYLOAD_SIZE[codeIndexNumber];
if (curLocation + channelMessageSize <= size) {
- outputStream.write(codeIndexNumber);
+ outputStream.write(codeIndexNumber | mShiftedCableNumber);
outputStream.write(midiBytes, curLocation, channelMessageSize);
// Fill in the rest of the bytes with 0.
outputStream.write(mEmptyBytes, 0, 3 - channelMessageSize);
@@ -197,8 +289,8 @@
curLocation++;
} else if (midiBytes[curLocation] == SYSEX_END_EXCLUSIVE) {
// 1 byte is 0x05, 2 bytes is 0x06, and 3 bytes is 0x07
- outputStream.write(CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
- + mNumStoredSystemExclusiveBytes);
+ outputStream.write((CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
+ + mNumStoredSystemExclusiveBytes) | mShiftedCableNumber);
mStoredSystemExclusiveBytes[mNumStoredSystemExclusiveBytes] =
midiBytes[curLocation];
mNumStoredSystemExclusiveBytes++;
@@ -218,7 +310,7 @@
} else {
int systemMessageSize = PAYLOAD_SIZE[codeIndexNumber];
if (curLocation + systemMessageSize <= size) {
- outputStream.write(codeIndexNumber);
+ outputStream.write(codeIndexNumber | mShiftedCableNumber);
outputStream.write(midiBytes, curLocation, systemMessageSize);
// Fill in the rest of the bytes with 0.
outputStream.write(mEmptyBytes, 0, 3 - systemMessageSize);
@@ -236,7 +328,7 @@
}
private void writeSingleByte(ByteArrayOutputStream outputStream, byte byteToWrite) {
- outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE);
+ outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE | mShiftedCableNumber);
outputStream.write(byteToWrite);
outputStream.write(0);
outputStream.write(0);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
index 1f448ac..117a3d9 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
@@ -118,7 +118,7 @@
mClassSpecificEndpointDescriptor = descriptor;
}
- UsbDescriptor getClassSpecificEndpointDescriptor() {
+ public UsbDescriptor getClassSpecificEndpointDescriptor() {
return mClassSpecificEndpointDescriptor;
}
diff --git a/services/voiceinteraction/TEST_MAPPING b/services/voiceinteraction/TEST_MAPPING
index d6c6964..5fe1c8d 100644
--- a/services/voiceinteraction/TEST_MAPPING
+++ b/services/voiceinteraction/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit-large": [
+ "presubmit": [
{
"name": "CtsVoiceInteractionTestCases",
"options": [
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 97538c1..50f2ad4 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -294,18 +294,21 @@
/**
* Raises an event to the {@link android.telecom.InCallService} implementations tracking this
* call via {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
- * These events and the associated extra keys for the {@code Bundle} parameter are defined
- * in Android X. This API is used to relay additional information about a call other than
- * what is specified in the {@link android.telecom.CallAttributes} to
- * {@link android.telecom.InCallService}s. This might include, for example, a change to the list
- * of participants in a meeting, or the name of the speakers who have their hand raised. Where
- * appropriate, the {@link InCallService}s tracking this call may choose to render this
- * additional information about the call. An automotive calling UX, for example may have enough
- * screen real estate to indicate the number of participants in a meeting, but to prevent
- * distractions could suppress the list of participants.
+ * These events and the associated extra keys for the {@code Bundle} parameter are mutually
+ * defined by a VoIP application and {@link android.telecom.InCallService}. This API is used to
+ * relay additional information about a call other than what is specified in the
+ * {@link android.telecom.CallAttributes} to {@link android.telecom.InCallService}s. This might
+ * include, for example, a change to the list of participants in a meeting, or the name of the
+ * speakers who have their hand raised. Where appropriate, the {@link InCallService}s tracking
+ * this call may choose to render this additional information about the call. An automotive
+ * calling UX, for example may have enough screen real estate to indicate the number of
+ * participants in a meeting, but to prevent distractions could suppress the list of
+ * participants.
*
- * @param event that is defined in AndroidX (ex. The number of participants changed)
- * @param extras the updated value in relation to the event (ex. 4 participants)
+ * @param event a string event identifier agreed upon between a VoIP application and an
+ * {@link android.telecom.InCallService}
+ * @param extras a {@link android.os.Bundle} containing information about the event, as agreed
+ * upon between a VoIP application and {@link android.telecom.InCallService}.
*/
public void sendEvent(@NonNull String event, @NonNull Bundle extras) {
Objects.requireNonNull(event);
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index d96c406..a41c011 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -60,14 +60,17 @@
/**
* Informs this {@link android.telecom.CallEventCallback} on events raised from a
- * {@link android.telecom.InCallService} presenting this call. The event key and extra values
- * are defined in AndroidX. This enables alternative calling surfaces, such as an automotive
- * UI, to relay requests to perform other non-standard call actions to the app. For example,
- * an automotive calling solution may offer the ability for the user to raise their hand
- * during a meeting.
+ * {@link android.telecom.InCallService} presenting this call. These events and the
+ * associated extra keys for the {@code Bundle} parameter are mutually defined by a VoIP
+ * application and {@link android.telecom.InCallService}. This enables alternative calling
+ * surfaces, such as an automotive UI, to relay requests to perform other non-standard call
+ * actions to the app. For example, an automotive calling solution may offer the ability for
+ * the user to raise their hand during a meeting.
*
- * @param event that is defined in AndroidX (ex. the number of participants changed)
- * @param extras the updated value in relation to the event (ex. 4 participants)
+ * @param event a string event identifier agreed upon between a VoIP application and an
+ * {@link android.telecom.InCallService}
+ * @param extras a {@link android.os.Bundle} containing information about the event, as agreed
+ * upon between a VoIP application and {@link android.telecom.InCallService}.
*/
void onEvent(@NonNull String event, @NonNull Bundle extras);
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index de99ebf..e39af5a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -895,9 +895,13 @@
"android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
/**
- * The intent to clear missed calls.
+ * Included in the extras of the {@link #ACTION_SHOW_MISSED_CALLS_NOTIFICATION}, provides a
+ * pending intent which can be used to clear the missed calls notification and mark unread
+ * missed call log entries as read.
* @hide
+ * @deprecated Use {@link #cancelMissedCallsNotification()} instead.
*/
+ @Deprecated
@SystemApi
public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT =
"android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
@@ -2073,6 +2077,14 @@
* {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
* {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
* <p>
+ * Specify the address associated with the incoming call using
+ * {@link #EXTRA_INCOMING_CALL_ADDRESS}. If an incoming call is from an anonymous source, omit
+ * this extra and ensure you specify a valid number presentation via
+ * {@link Connection#setAddress(Uri, int)} on the {@link Connection} instance you return in
+ * your
+ * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+ * implementation.
+ * <p>
* The incoming call you are adding is assumed to have a video state of
* {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value
* {@link #EXTRA_INCOMING_VIDEO_STATE} is specified.
@@ -2254,9 +2266,10 @@
}
/**
- * Removes the missed-call notification if one is present.
+ * Removes the missed-call notification if one is present and marks missed calls in the call
+ * log as read.
* <p>
- * Requires that the method-caller be set as the system dialer app.
+ * Requires that the method-caller be set as the default dialer app.
* </p>
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 77af956..918ae79 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -537,10 +537,9 @@
/**
* CDMA activation goes through OTASP.
- * <p>
- * TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum
- * (NONE, HFA, OTASP).
*/
+ // TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum
+ // (NONE, HFA, OTASP).
public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL =
"use_otasp_for_provisioning_bool";
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 3e2c7c4..758372a 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3964,7 +3964,12 @@
/** @hide */
public static void invalidateActiveDataSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
+ if (isSubscriptionManagerServiceEnabled()) {
+ PropertyInvalidatedCache.invalidateCache(
+ CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
+ } else {
+ PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
+ }
}
/** @hide */
diff --git a/tests/EnforcePermission/Android.bp b/tests/EnforcePermission/Android.bp
new file mode 100644
index 0000000..719a898
--- /dev/null
+++ b/tests/EnforcePermission/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+ name: "frameworks-enforce-permission-test-aidl",
+ srcs: ["aidl/**/*.aidl"],
+}
diff --git a/tests/EnforcePermission/OWNERS b/tests/EnforcePermission/OWNERS
new file mode 100644
index 0000000..39550a3
--- /dev/null
+++ b/tests/EnforcePermission/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 315013
+tweek@google.com
+brufino@google.com
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
similarity index 71%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
index 35d5c15..1eb773d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
@@ -14,6 +14,12 @@
* limitations under the License.
*/
-package android.net.wifi.sharedconnectivity.app;
+package android.tests.enforcepermission;
-parcelable DeviceInfo;
\ No newline at end of file
+interface INested {
+ @EnforcePermission("ACCESS_NETWORK_STATE")
+ void ProtectedByAccessNetworkState();
+
+ @EnforcePermission("READ_SYNC_SETTINGS")
+ void ProtectedByReadSyncSettings();
+}
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
new file mode 100644
index 0000000..18e3aec
--- /dev/null
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tests.enforcepermission;
+
+interface IProtected {
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternet();
+
+ @EnforcePermission("VIBRATE")
+ void ProtectedByVibrate();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndVibrateImplicitly();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndAccessNetworkStateImplicitly();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndReadSyncSettingsImplicitly();
+}
diff --git a/tests/EnforcePermission/service-app/Android.bp b/tests/EnforcePermission/service-app/Android.bp
new file mode 100644
index 0000000..a4ac1d7
--- /dev/null
+++ b/tests/EnforcePermission/service-app/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "EnforcePermissionTestHelper",
+ srcs: [
+ "src/**/*.java",
+ ":frameworks-enforce-permission-test-aidl",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tests/EnforcePermission/service-app/AndroidManifest.xml b/tests/EnforcePermission/service-app/AndroidManifest.xml
new file mode 100644
index 0000000..ddafe15
--- /dev/null
+++ b/tests/EnforcePermission/service-app/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tests.enforcepermission.service">
+ <application>
+ <service
+ android:name=".TestService"
+ android:exported="true" />
+
+ <service
+ android:name=".NestedTestService"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
new file mode 100644
index 0000000..7879a12
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.tests.enforcepermission.INested;
+import android.util.Log;
+
+public class NestedTestService extends Service {
+ private static final String TAG = "EnforcePermission.NestedTestService";
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.i(TAG, "onBind");
+ return mBinder;
+ }
+
+ private final INested.Stub mBinder = new INested.Stub() {
+ @Override
+ @EnforcePermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ public void ProtectedByAccessNetworkState() {
+ ProtectedByAccessNetworkState_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.READ_SYNC_SETTINGS)
+ public void ProtectedByReadSyncSettings() {
+ ProtectedByReadSyncSettings_enforcePermission();
+ }
+ };
+}
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
new file mode 100644
index 0000000..e9b897d
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.INested;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class TestService extends Service {
+
+ private static final String TAG = "EnforcePermission.TestService";
+ private volatile ServiceConnection mNestedServiceConnection;
+
+ @Override
+ public void onCreate() {
+ mNestedServiceConnection = new ServiceConnection();
+ Intent intent = new Intent(this, NestedTestService.class);
+ boolean bound = bindService(intent, mNestedServiceConnection, Context.BIND_AUTO_CREATE);
+ if (!bound) {
+ Log.wtf(TAG, "bindService() on NestedTestService failed");
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ unbindService(mNestedServiceConnection);
+ }
+
+ private static final class ServiceConnection implements android.content.ServiceConnection {
+ private volatile CompletableFuture<INested> mFuture = new CompletableFuture<>();
+
+ public INested get() {
+ try {
+ return mFuture.get(1, TimeUnit.SECONDS);
+ } catch (ExecutionException | InterruptedException | TimeoutException e) {
+ throw new RuntimeException("Unable to reach NestedTestService: " + e.getMessage());
+ }
+ }
+
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mFuture.complete(INested.Stub.asInterface(service));
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ mFuture = new CompletableFuture<>();
+ }
+ };
+
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ private final IProtected.Stub mBinder = new IProtected.Stub() {
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternet() {
+ ProtectedByInternet_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.VIBRATE)
+ public void ProtectedByVibrate() {
+ ProtectedByVibrate_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndVibrateImplicitly() {
+ ProtectedByInternetAndVibrateImplicitly_enforcePermission();
+
+ ProtectedByVibrate();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndAccessNetworkStateImplicitly() throws RemoteException {
+ ProtectedByInternetAndAccessNetworkStateImplicitly_enforcePermission();
+
+ mNestedServiceConnection.get().ProtectedByAccessNetworkState();
+
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndReadSyncSettingsImplicitly() throws RemoteException {
+ ProtectedByInternetAndReadSyncSettingsImplicitly_enforcePermission();
+
+ mNestedServiceConnection.get().ProtectedByReadSyncSettings();
+ }
+ };
+}
diff --git a/tests/EnforcePermission/test-app/Android.bp b/tests/EnforcePermission/test-app/Android.bp
new file mode 100644
index 0000000..305ed8f
--- /dev/null
+++ b/tests/EnforcePermission/test-app/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "EnforcePermissionTests",
+ srcs: [
+ "src/**/*.java",
+ ":frameworks-enforce-permission-test-aidl",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ ],
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ ],
+ data: [
+ ":EnforcePermissionTestHelper",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["general-tests"],
+}
diff --git a/tests/EnforcePermission/test-app/AndroidManifest.xml b/tests/EnforcePermission/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..4a0c6a8
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tests.enforcepermission.tests">
+
+ <!-- Expected for the tests (not actually used) -->
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+
+ <queries>
+ <package android:name="android.tests.enforcepermission.service" />
+ </queries>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.tests.enforcepermission.tests"/>
+</manifest>
diff --git a/tests/EnforcePermission/test-app/AndroidTest.xml b/tests/EnforcePermission/test-app/AndroidTest.xml
new file mode 100644
index 0000000..120381a
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Runs EnforcePermission End-to-End Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="EnforcePermissionTestHelper.apk"/>
+ <option name="test-file-name" value="EnforcePermissionTests.apk"/>
+ <option name="cleanup-apks" value="true" />
+ </target_preparer>
+
+ <option name="test-tag" value="EnforcePermissionTests"/>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="android.tests.enforcepermission.tests"/>
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
diff --git a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
new file mode 100644
index 0000000..d2a4a03
--- /dev/null
+++ b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tests.enforcepermission.tests;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class ServiceTest {
+
+ private static final String TAG = "EnforcePermission.Tests";
+ private static final String SERVICE_NAME = "android.tests.enforcepermission.service";
+ private static final int SERVICE_TIMEOUT_SEC = 5;
+
+ private Context mContext;
+ private volatile ServiceConnection mServiceConnection;
+
+ @Before
+ public void bindTestService() throws Exception {
+ Log.d(TAG, "bindTestService");
+ mContext = InstrumentationRegistry.getTargetContext();
+ mServiceConnection = new ServiceConnection();
+ Intent intent = new Intent();
+ intent.setClassName(SERVICE_NAME, SERVICE_NAME + ".TestService");
+ assertTrue(mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE));
+ }
+
+ @After
+ public void unbindTestService() throws Exception {
+ mContext.unbindService(mServiceConnection);
+ }
+
+ private static final class ServiceConnection implements android.content.ServiceConnection {
+ private volatile CompletableFuture<IProtected> mFuture = new CompletableFuture<>();
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mFuture.complete(IProtected.Stub.asInterface(service));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mFuture = new CompletableFuture<>();
+ }
+
+ public IProtected get() {
+ try {
+ return mFuture.get(SERVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (ExecutionException | InterruptedException | TimeoutException e) {
+ throw new RuntimeException("Unable to reach TestService: " + e.toString());
+ }
+ }
+ }
+
+ @Test
+ public void testImmediatePermissionGranted_succeeds()
+ throws RemoteException {
+ mServiceConnection.get().ProtectedByInternet();
+ }
+
+ @Test
+ public void testImmediatePermissionNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get().ProtectedByVibrate());
+ assertThat(ex.getMessage(), containsString("VIBRATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedButImplicitLocalNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get().ProtectedByInternetAndVibrateImplicitly());
+ assertThat(ex.getMessage(), containsString("VIBRATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedButImplicitNestedNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get()
+ .ProtectedByInternetAndAccessNetworkStateImplicitly());
+ assertThat(ex.getMessage(), containsString("ACCESS_NETWORK_STATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedAndImplicitNestedGranted_succeeds()
+ throws RemoteException {
+ mServiceConnection.get().ProtectedByInternetAndReadSyncSettingsImplicitly();
+ }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
index 858cd76..70dcc12 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
@@ -20,6 +20,7 @@
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.os.SystemClock;
+import android.util.Log;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
@@ -30,6 +31,7 @@
* Injects gestures given an {@link Instrumentation} object.
*/
public class GestureHelper {
+ private static final String TAG = GestureHelper.class.getSimpleName();
// Inserted after each motion event injection.
private static final int MOTION_EVENT_INJECTION_DELAY_MILLIS = 5;
@@ -153,6 +155,9 @@
for (int j = 0; j < coords.length; j++) {
coords[j].x += (endPoints[j].x - startPoints[j].x) / steps;
coords[j].y += (endPoints[j].y - startPoints[j].y) / steps;
+
+ // TODO: remove logging once b/269505548 is resolved
+ Log.d(TAG, "(" + coords[j].x + ", " + coords[j].y + ")");
}
eventTime = SystemClock.uptimeMillis();
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
new file mode 100644
index 0000000..1ccac13
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 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.wm.flicker.helpers
+
+import android.app.Instrumentation
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.testapp.ActivityOptions
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.traces.parsers.toFlickerComponent
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.helpers.SYSTEMUI_PACKAGE
+
+class LetterboxAppHelper
+@JvmOverloads
+constructor(
+ instr: Instrumentation,
+ launcherName: String = ActivityOptions.NonResizeablePortraitActivity.LABEL,
+ component: ComponentNameMatcher =
+ ActivityOptions.NonResizeablePortraitActivity.COMPONENT.toFlickerComponent()
+) : StandardAppHelper(instr, launcherName, component) {
+
+ fun clickRestart(wmHelper: WindowManagerStateHelper) {
+ val restartButton = uiDevice.wait(Until.findObject(By.res(
+ SYSTEMUI_PACKAGE, "size_compat_restart_button")), FIND_TIMEOUT)
+ restartButton?.run { restartButton.click() } ?: error("Restart button not found")
+
+ // size compat mode restart confirmation dialog button
+ val restartDialogButton = uiDevice.wait(Until.findObject(By.res(
+ SYSTEMUI_PACKAGE, "letterbox_restart_dialog_restart_button")), FIND_TIMEOUT)
+ restartDialogButton?.run { restartDialogButton.click() }
+ ?: error("Restart dialog button not found")
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
+ }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
index 5361d73f..1ec9ec9 100644
--- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -88,6 +88,18 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
+ <activity android:name=".NonResizeablePortraitActivity"
+ android:theme="@style/CutoutNever"
+ android:resizeableActivity="false"
+ android:screenOrientation="portrait"
+ android:taskAffinity="com.android.server.wm.flicker.testapp.NonResizeablePortraitActivity"
+ android:label="NonResizeablePortraitActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
<activity android:name=".LaunchNewActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.LaunchNewActivity"
android:theme="@style/CutoutShortEdges"
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
index b61bc0c..9c3226b 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
@@ -67,6 +67,12 @@
FLICKER_APP_PACKAGE + ".NonResizeableActivity");
}
+ public static class NonResizeablePortraitActivity {
+ public static final String LABEL = "NonResizeablePortraitActivity";
+ public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+ FLICKER_APP_PACKAGE + ".NonResizeablePortraitActivity");
+ }
+
public static class DialogThemedActivity {
public static final String LABEL = "DialogThemedActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NonResizeablePortraitActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NonResizeablePortraitActivity.java
new file mode 100644
index 0000000..4b420dc
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/NonResizeablePortraitActivity.java
@@ -0,0 +1,29 @@
+/*
+ * 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.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class NonResizeablePortraitActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.activity_non_resizeable);
+ }
+}
diff --git a/tests/MidiTests/Android.bp b/tests/MidiTests/Android.bp
new file mode 100644
index 0000000..254770d
--- /dev/null
+++ b/tests/MidiTests/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "MidiTests",
+ srcs: ["**/*.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "mockito-target-inline-minus-junit4",
+ "platform-test-annotations",
+ "services.midi",
+ "truth-prebuilt",
+ ],
+ jni_libs: ["libdexmakerjvmtiagent"],
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: ["device-tests"],
+}
diff --git a/tests/MidiTests/AndroidManifest.xml b/tests/MidiTests/AndroidManifest.xml
new file mode 100644
index 0000000..0ee1b449
--- /dev/null
+++ b/tests/MidiTests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.midi" >
+
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.midi"
+ android:label="MidiTests"/>
+</manifest>
diff --git a/tests/MidiTests/AndroidTest.xml b/tests/MidiTests/AndroidTest.xml
new file mode 100644
index 0000000..9320f0a
--- /dev/null
+++ b/tests/MidiTests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Runs sample instrumentation test.">
+ <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="MidiTests.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="MidiTests"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.server.midi"/>
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/tests/MidiTests/OWNERS b/tests/MidiTests/OWNERS
new file mode 100644
index 0000000..af273a6
--- /dev/null
+++ b/tests/MidiTests/OWNERS
@@ -0,0 +1 @@
+include /services/midi/OWNERS
diff --git a/tests/MidiTests/TEST_MAPPING b/tests/MidiTests/TEST_MAPPING
new file mode 100644
index 0000000..60416a8
--- /dev/null
+++ b/tests/MidiTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "MidiTests"
+ }
+ ]
+}
diff --git a/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
new file mode 100644
index 0000000..1659cc0
--- /dev/null
+++ b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2023 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.midi;
+
+import static org.junit.Assert.assertEquals;
+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 androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiEventMultiScheduler;
+import com.android.internal.midi.MidiEventScheduler;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.internal.midi.MidiEventMultiScheduler.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MidiEventMultiSchedulerTest {
+ private byte[] generateRandomByteStream(Random rnd, int size) {
+ byte[] output = new byte[size];
+ rnd.nextBytes(output);
+ return output;
+ }
+
+ private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+ assertEquals(expectedArray.length, outputArray.length);
+ for (int i = 0; i < outputArray.length; i++) {
+ assertEquals(expectedArray[i], outputArray[i]);
+ }
+ }
+
+ private long timeFromNow(long milliseconds) {
+ return System.nanoTime() + 1000000L * milliseconds;
+ }
+
+ @Test
+ public void testMultiScheduler() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0, (byte) 0xf7},
+ 0, 2, timeFromNow(100)));
+ scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1, (byte) 0xf2},
+ 0, 2, timeFromNow(200)));
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf3, (byte) 0xf4},
+ 0, 2, timeFromNow(300)));
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+ 0, 2, timeFromNow(400)));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNotNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNotNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerLargeData() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+
+ Random rnd = new Random(42);
+
+ final int arraySize = 1000;
+ byte[] expectedArray = generateRandomByteStream(rnd, arraySize);
+
+ scheduler0.add(scheduler0.createScheduledEvent(expectedArray, 0, arraySize,
+ timeFromNow(100)));
+ assertTrue(multiScheduler.waitNextEvent());
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ compareByteArrays(expectedArray, event.data);
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerClose() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ scheduler0.close();
+ // After all schedulers are closed, waitNextEvent() should return false.
+ assertFalse(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerMultiClose() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ multiScheduler.close();
+ // After all schedulers are closed, waitNextEvent() should return false.
+ assertFalse(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerNoPreemptiveClose() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+ scheduler0.close();
+ scheduler1.close();
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+ 0, 2, timeFromNow(100)));
+ assertTrue(multiScheduler.waitNextEvent());
+ scheduler2.close();
+ // After all schedulers are closed, waitNextEvent() should return false.
+ assertFalse(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerSpamEvents() {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ // Create a msg with size 1
+ byte[] msg = new byte[1];
+ for (int i = 0; i < 1000; i++) {
+ msg[0] = (byte) i;
+ scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals(msg[0], event.data[0]);
+ }
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ }
+
+ @Test
+ public void testSchedulerSpamEventsPullLater() {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ // Create a msg with size 1
+ byte[] msg = new byte[1];
+ for (int i = 0; i < 1000; i++) {
+ msg[0] = (byte) i;
+ scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+ }
+
+ for (int i = 0; i < 1000; i++) {
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) i, event.data[0]);
+ }
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ }
+
+ @Test
+ public void testSchedulerSpamEventsCallbackLater() {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ // Create a msg with size 1
+ byte[] msg = new byte[1];
+ for (int i = 0; i < 1000; i++) {
+ msg[0] = (byte) i;
+ scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+ }
+
+ for (int i = 0; i < 1000; i++) {
+ try {
+ assertTrue(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+ }
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) i, event.data[0]);
+ }
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ }
+
+ @Test
+ public void testMultiSchedulerOutOfOrder() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+ 0, 1,
+ timeFromNow(400)));
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+ 0, 1,
+ timeFromNow(300)));
+ scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+ 0, 1,
+ timeFromNow(200)));
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+ 0, 1,
+ timeFromNow(100)));
+
+ assertTrue(multiScheduler.waitNextEvent());
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf0, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf1, event.data[0]);
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf2, event.data[0]);
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf3, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testMultiSchedulerOutOfOrderNegativeTime() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+ 0, 1,
+ timeFromNow(-100)));
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+ 0, 1,
+ timeFromNow(-200)));
+ scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+ 0, 1,
+ timeFromNow(-300)));
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+ 0, 1,
+ timeFromNow(-400)));
+
+ assertTrue(multiScheduler.waitNextEvent());
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf0, event.data[0]);
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf1, event.data[0]);
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf2, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf3, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ } catch (InterruptedException ex) {
+
+ }
+ }
+}
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
index 3875644..e079b6d 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
@@ -80,10 +80,10 @@
spinner.adapter = adapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
- parent: AdapterView<*>?,
- view: View?,
- position: Int,
- id: Long
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
) {
setImage(position)
}
@@ -108,7 +108,7 @@
if (selectedImage == position) return
selectedImage = position
val source = ImageDecoder.createSource(resources.assets,
- "gainmaps/${gainmapImages[position]}")
+ "gainmaps/${gainmapImages[position]}")
doDecode(source)
}
@@ -137,16 +137,16 @@
gainmapVisualizer = map
} else {
gainmapVisualizer = Bitmap.createBitmap(map.width, map.height,
- Bitmap.Config.ARGB_8888)
+ Bitmap.Config.ARGB_8888)
val canvas = Canvas(gainmapVisualizer!!)
val paint = Paint()
paint.colorFilter = ColorMatrixColorFilter(
- floatArrayOf(
- 0f, 0f, 0f, 1f, 0f,
- 0f, 0f, 0f, 1f, 0f,
- 0f, 0f, 0f, 1f, 0f,
- 0f, 0f, 0f, 0f, 255f
- )
+ floatArrayOf(
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 0f, 255f
+ )
)
canvas.drawBitmap(map, 0f, 0f, paint)
canvas.setBitmap(null)
@@ -174,8 +174,14 @@
if (bitmap == null) return
imageView.setImage(ImageSource.cachedBitmap(when (outputMode) {
- R.id.output_hdr -> { bitmap!!.gainmap = gainmap; bitmap!! }
- R.id.output_sdr -> { bitmap!!.gainmap = null; bitmap!! }
+ R.id.output_hdr -> {
+ bitmap!!.gainmap = gainmap; bitmap!!
+ }
+
+ R.id.output_sdr -> {
+ bitmap!!.gainmap = null; bitmap!!
+ }
+
R.id.output_gainmap -> gainmapVisualizer!!
else -> throw IllegalStateException()
}))
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java
new file mode 100644
index 0000000..ad701e5
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2023 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.usb;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.server.usb.UsbMidiPacketConverter.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class UsbMidiPacketConverterTest {
+ private byte[] generateRandomByteStream(Random rnd, int size) {
+ byte[] output = new byte[size];
+ rnd.nextBytes(output);
+ return output;
+ }
+
+ private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+ assertEquals(expectedArray.length, outputArray.length);
+ for (int i = 0; i < outputArray.length; i++) {
+ assertEquals(expectedArray[i], outputArray[i]);
+ }
+ }
+
+ @Test
+ public void testDecoderSinglePacket() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(2);
+ byte[] input = new byte[] {0x19 /* Cable 1 Note-On */, (byte) 0x91, 0x33, 0x66};
+ byte[] expectedOutputCable0 = new byte[] {};
+ byte[] expectedOutputCable1 = new byte[] {(byte) 0x91, 0x33, 0x66};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ compareByteArrays(expectedOutputCable1, actualOutputCable1);
+ }
+
+ @Test
+ public void testDecoderMultiplePackets() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(4);
+ byte[] input = new byte[] {
+ 0x1B /* Cable 1 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+ 0x35 /* Cable 3 Single byte SysEx */, (byte) 0xF8, 0x00, 0x00,
+ 0x02 /* Cable 0 Two byte System Common */, (byte) 0xF3, 0x12, 0x00};
+ byte[] expectedOutputCable0 = new byte[] {(byte) 0xF3, 0x12};
+ byte[] expectedOutputCable1 = new byte[] {(byte) 0xB4, 0x55, 0x6E};
+ byte[] expectedOutputCable2 = new byte[] {};
+ byte[] expectedOutputCable3 = new byte[] {(byte) 0xF8};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ byte[] actualOutputCable2 = usbMidiPacketConverter.pullDecodedMidiPackets(2);
+ byte[] actualOutputCable3 = usbMidiPacketConverter.pullDecodedMidiPackets(3);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ compareByteArrays(expectedOutputCable1, actualOutputCable1);
+ compareByteArrays(expectedOutputCable2, actualOutputCable2);
+ compareByteArrays(expectedOutputCable3, actualOutputCable3);
+ }
+
+ @Test
+ public void testDecoderSysExEndFirstByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(2);
+ byte[] input = new byte[] {
+ 0x14 /* Cable 1 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x15 /* Cable 1 Single byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+ byte[] expectedOutputCable0 = new byte[] {};
+ byte[] expectedOutputCable1 = new byte[] {
+ (byte) 0xF0, 0x00, 0x01,
+ (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ compareByteArrays(expectedOutputCable1, actualOutputCable1);
+ }
+
+ @Test
+ public void testDecoderSysExEndSecondByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] input = new byte[] {
+ 0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x06 /* Cable 0 Two byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, 0x00, 0x01,
+ 0x02, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderSysExEndThirdByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {
+ 0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x07 /* Cable 0 Three byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, 0x00, 0x01,
+ 0x02, 0x03, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderSysExStartEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {
+ 0x06 /* Cable 0 Two byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderSysExStartByteEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {
+ 0x07 /* Cable 0 Three byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, 0x44, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderDefaultToFirstCable() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {0x49 /* Cable 4 Note-On */, (byte) 0x91, 0x22, 0x33};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0x91, 0x22, 0x33};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderLargePacketDoesNotCrash() {
+ for (long seed = 1001; seed < 5000; seed += 777) {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(3);
+ Random rnd = new Random(seed);
+ byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ usbMidiPacketConverter.pullDecodedMidiPackets(2);
+ }
+ }
+
+ @Test
+ public void testEncoderBasic() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x33, 0x66};
+ byte[] expectedOutput = new byte[] {
+ 0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x33, 0x66};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderMultiplePackets() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(3);
+ byte[] inputCable2 = new byte[] {
+ (byte) 0xB4 /* Control Change */, 0x55, 0x6E};
+ byte[] inputCable1 = new byte[] {
+ (byte) 0xF8 /* Timing Clock (Single Byte) */,
+ (byte) 0xF3 /* Song Select (Two Bytes) */, 0x12};
+ byte[] expectedOutput = new byte[] {
+ 0x2B /* Cable 2 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+ 0x15 /* Cable 1 Timing Clock */, (byte) 0xF8, 0x00, 0x00,
+ 0x12 /* Cable 1 Two Byte System Common */, (byte) 0xF3, 0x12, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(inputCable2, inputCable2.length, 2);
+ usbMidiPacketConverter.encodeMidiPackets(inputCable1, inputCable1.length, 1);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderWeavePackets() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(2);
+ byte[] inputCable1Msg1 = new byte[] {
+ (byte) 0x93 /* Note-On */, 0x23, 0x43};
+ byte[] inputCable0Msg = new byte[] {
+ (byte) 0xB4 /* Control Change */, 0x65, 0x26};
+ byte[] inputCable1Msg2 = new byte[] {
+ (byte) 0xA4 /* Poly-KeyPress */, 0x52, 0x76};
+ byte[] expectedOutput = new byte[] {
+ 0x19 /* Cable 1 Note-On */, (byte) 0x93, 0x23, 0x43,
+ 0x0B /* Cable 0 Control Change */, (byte) 0xB4, 0x65, 0x26,
+ 0x1A /* Cable 1 Poly-KeyPress */, (byte) 0xA4, 0x52, 0x76};
+ usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg1, inputCable1Msg1.length, 1);
+ usbMidiPacketConverter.encodeMidiPackets(inputCable0Msg, inputCable0Msg.length, 0);
+ usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg2, inputCable1Msg2.length, 1);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExEndFirstByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+ (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x05 /* Cable 0 One Byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExEndSecondByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+ 0x02, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x06 /* Cable 0 Two Byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExEndThirdByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+ 0x02, 0x03, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x07 /* Cable 0 Three Byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExStartEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExStartByteEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x44, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x07 /* Cable 0 Three Byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderMultiplePulls() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x44, 0x55,
+ 0x66, 0x77}; // 0x66 and 0x77 will not be pulled the first time
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* SysEx Start */, (byte) 0xF0, 0x44, 0x55};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+
+ input = new byte[] {
+ 0x11, // Combined with 0x66 and 0x77 above
+ 0x22, (byte) 0xF7 /* SysEx End */};
+ expectedOutput = new byte[] {
+ 0x04 /* Cable 0 SysEx Continue */, 0x66, 0x77, 0x11,
+ 0x06 /* Cable 0 Two Byte SysEx End */, 0x22, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+
+ input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+ expectedOutput = new byte[] {
+ 0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderDefaultToFirstCable() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(2);
+ byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x22, 0x33};
+ byte[] expectedOutput = new byte[] {
+ 0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x22, 0x33};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 4);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderLargePacketDoesNotCrash() {
+ for (long seed = 234; seed < 4000; seed += 666) {
+ Random rnd = new Random(seed);
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(4);
+ for (int cableNumber = 0; cableNumber < 4; cableNumber++) {
+ byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, cableNumber);
+ }
+ usbMidiPacketConverter.pullEncodedMidiPackets();
+ }
+ }
+
+ @Test
+ public void testEncodeDecode() {
+ final int bufferSize = 30;
+ final int numCables = 16;
+ final int bytesToEncodePerEncoding = 10;
+ byte[][] rawMidi = new byte[numCables][bufferSize];
+ for (long seed = 45; seed < 3000; seed += 300) {
+ Random rnd = new Random(seed);
+ for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+ rawMidi[cableNumber] = generateRandomByteStream(rnd, bufferSize);
+
+ // Change the last byte to SysEx End.
+ // This way the encoder is guaranteed to flush all packets.
+ rawMidi[cableNumber][bufferSize - 1] = (byte) 0xF7;
+ }
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(numCables);
+ // Encode packets and interweave them
+ for (int startByte = 0; startByte < bufferSize;
+ startByte += bytesToEncodePerEncoding) {
+ for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+ byte[] bytesToEncode = Arrays.copyOfRange(rawMidi[cableNumber], startByte,
+ startByte + bytesToEncodePerEncoding);
+ usbMidiPacketConverter.encodeMidiPackets(bytesToEncode, bytesToEncode.length,
+ cableNumber);
+ }
+ }
+ byte[] usbMidi = usbMidiPacketConverter.pullEncodedMidiPackets();
+
+ usbMidiPacketConverter.createDecoders(numCables);
+
+ // Now decode the MIDI packets to check if they are the same as the original
+ usbMidiPacketConverter.decodeMidiPackets(usbMidi, usbMidi.length);
+ for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+ byte[] decodedRawMidi = usbMidiPacketConverter.pullDecodedMidiPackets(cableNumber);
+ compareByteArrays(rawMidi[cableNumber], decodedRawMidi);
+ }
+ }
+ }
+}
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 7b94e71..34a1b11 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -15,7 +15,7 @@
$(aapt2_results): $(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests
-$(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests --gtest_output=xml:$@ > /dev/null 2>&1
-$(call declare-0p-target,$(aapt2_results))
+$(call declare-1p-target,$(aapt2_results))
aapt2_results :=
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
similarity index 95%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
index 35d5c15..f9c4829 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.sharedconnectivity.app;
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable HotspotNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
similarity index 76%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
index 7b591d3..d3b7b12 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
@@ -33,14 +33,14 @@
import java.util.Set;
/**
- * A data class representing an Instant Tether network.
+ * A data class representing a hotspot network.
* This class is used in IPC calls between the implementer of {@link SharedConnectivityService} and
* the consumers of {@link com.android.wifitrackerlib}.
*
* @hide
*/
@SystemApi
-public final class TetherNetwork implements Parcelable {
+public final class HotspotNetwork implements Parcelable {
/**
* Remote device is connected to the internet via an unknown connection.
*/
@@ -71,33 +71,44 @@
NETWORK_TYPE_WIFI,
NETWORK_TYPE_ETHERNET
})
- public @interface NetworkType {}
+ public @interface NetworkType {
+ }
private final long mDeviceId;
- private final DeviceInfo mDeviceInfo;
- @NetworkType private final int mNetworkType;
+ private final NetworkProviderInfo mNetworkProviderInfo;
+ @NetworkType
+ private final int mNetworkType;
private final String mNetworkName;
- @Nullable private final String mHotspotSsid;
- @Nullable private final String mHotspotBssid;
- @Nullable @SecurityType private final ArraySet<Integer> mHotspotSecurityTypes;
+ @Nullable
+ private final String mHotspotSsid;
+ @Nullable
+ private final String mHotspotBssid;
+ @Nullable
+ @SecurityType
+ private final ArraySet<Integer> mHotspotSecurityTypes;
/**
- * Builder class for {@link TetherNetwork}.
+ * Builder class for {@link HotspotNetwork}.
*/
public static final class Builder {
private long mDeviceId = -1;
- private DeviceInfo mDeviceInfo;
- @NetworkType private int mNetworkType;
+ private NetworkProviderInfo mNetworkProviderInfo;
+ @NetworkType
+ private int mNetworkType;
private String mNetworkName;
- @Nullable private String mHotspotSsid;
- @Nullable private String mHotspotBssid;
- @Nullable @SecurityType private final ArraySet<Integer> mHotspotSecurityTypes =
+ @Nullable
+ private String mHotspotSsid;
+ @Nullable
+ private String mHotspotBssid;
+ @Nullable
+ @SecurityType
+ private final ArraySet<Integer> mHotspotSecurityTypes =
new ArraySet<>();
/**
* Set the remote device ID.
*
- * @param deviceId Locally unique ID for this Instant Tether network.
+ * @param deviceId Locally unique ID for this Hotspot network.
* @return Returns the Builder object.
*/
@NonNull
@@ -109,12 +120,12 @@
/**
* Sets information about the device providing connectivity.
*
- * @param deviceInfo The device information object.
+ * @param networkProviderInfo The device information object.
* @return Returns the Builder object.
*/
@NonNull
- public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
- mDeviceInfo = deviceInfo;
+ public Builder setNetworkProviderInfo(@NonNull NetworkProviderInfo networkProviderInfo) {
+ mNetworkProviderInfo = networkProviderInfo;
return this;
}
@@ -125,7 +136,7 @@
* @return Returns the Builder object.
*/
@NonNull
- public Builder setNetworkType(@NetworkType int networkType) {
+ public Builder setHostNetworkType(@NetworkType int networkType) {
mNetworkType = networkType;
return this;
}
@@ -179,15 +190,15 @@
}
/**
- * Builds the {@link TetherNetwork} object.
+ * Builds the {@link HotspotNetwork} object.
*
- * @return Returns the built {@link TetherNetwork} object.
+ * @return Returns the built {@link HotspotNetwork} object.
*/
@NonNull
- public TetherNetwork build() {
- return new TetherNetwork(
+ public HotspotNetwork build() {
+ return new HotspotNetwork(
mDeviceId,
- mDeviceInfo,
+ mNetworkProviderInfo,
mNetworkType,
mNetworkName,
mHotspotSsid,
@@ -196,7 +207,7 @@
}
}
- private static void validate(long deviceId, int networkType, String networkName) {
+ private static void validate(long deviceId, @NetworkType int networkType, String networkName) {
if (deviceId < 0) {
throw new IllegalArgumentException("DeviceId must be set");
}
@@ -209,9 +220,9 @@
}
}
- private TetherNetwork(
+ private HotspotNetwork(
long deviceId,
- DeviceInfo deviceInfo,
+ NetworkProviderInfo networkProviderInfo,
@NetworkType int networkType,
@NonNull String networkName,
@Nullable String hotspotSsid,
@@ -221,7 +232,7 @@
networkType,
networkName);
mDeviceId = deviceId;
- mDeviceInfo = deviceInfo;
+ mNetworkProviderInfo = networkProviderInfo;
mNetworkType = networkType;
mNetworkName = networkName;
mHotspotSsid = hotspotSsid;
@@ -232,7 +243,7 @@
/**
* Gets the remote device ID.
*
- * @return Returns the locally unique ID for this Instant Tether network.
+ * @return Returns the locally unique ID for this Hotspot network.
*/
public long getDeviceId() {
return mDeviceId;
@@ -241,11 +252,11 @@
/**
* Gets information about the device providing connectivity.
*
- * @return Returns the information of the device providing the Instant Tether network.
+ * @return Returns the information of the device providing the Hotspot network.
*/
@NonNull
- public DeviceInfo getDeviceInfo() {
- return mDeviceInfo;
+ public NetworkProviderInfo getNetworkProviderInfo() {
+ return mNetworkProviderInfo;
}
/**
@@ -254,7 +265,7 @@
* @return Returns the network type as represented by IntDef {@link NetworkType}.
*/
@NetworkType
- public int getNetworkType() {
+ public int getHostNetworkType() {
return mNetworkType;
}
@@ -301,11 +312,11 @@
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof TetherNetwork)) return false;
- TetherNetwork other = (TetherNetwork) obj;
+ if (!(obj instanceof HotspotNetwork)) return false;
+ HotspotNetwork other = (HotspotNetwork) obj;
return mDeviceId == other.getDeviceId()
- && Objects.equals(mDeviceInfo, other.getDeviceInfo())
- && mNetworkType == other.getNetworkType()
+ && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo())
+ && mNetworkType == other.getHostNetworkType()
&& Objects.equals(mNetworkName, other.getNetworkName())
&& Objects.equals(mHotspotSsid, other.getHotspotSsid())
&& Objects.equals(mHotspotBssid, other.getHotspotBssid())
@@ -314,8 +325,8 @@
@Override
public int hashCode() {
- return Objects.hash(mDeviceId, mDeviceInfo, mNetworkName, mHotspotSsid, mHotspotBssid,
- mHotspotSecurityTypes);
+ return Objects.hash(mDeviceId, mNetworkProviderInfo, mNetworkName, mHotspotSsid,
+ mHotspotBssid, mHotspotSecurityTypes);
}
@Override
@@ -326,7 +337,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mDeviceId);
- mDeviceInfo.writeToParcel(dest, flags);
+ mNetworkProviderInfo.writeToParcel(dest, flags);
dest.writeInt(mNetworkType);
dest.writeString(mNetworkName);
dest.writeString(mHotspotSsid);
@@ -335,36 +346,36 @@
}
/**
- * Creates a {@link TetherNetwork} object from a parcel.
+ * Creates a {@link HotspotNetwork} object from a parcel.
*
* @hide
*/
@NonNull
- public static TetherNetwork readFromParcel(@NonNull Parcel in) {
- return new TetherNetwork(in.readLong(), DeviceInfo.readFromParcel(in),
+ public static HotspotNetwork readFromParcel(@NonNull Parcel in) {
+ return new HotspotNetwork(in.readLong(), NetworkProviderInfo.readFromParcel(in),
in.readInt(), in.readString(), in.readString(), in.readString(),
(ArraySet<Integer>) in.readArraySet(null));
}
@NonNull
- public static final Creator<TetherNetwork> CREATOR = new Creator<>() {
+ public static final Creator<HotspotNetwork> CREATOR = new Creator<>() {
@Override
- public TetherNetwork createFromParcel(Parcel in) {
+ public HotspotNetwork createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
- public TetherNetwork[] newArray(int size) {
- return new TetherNetwork[size];
+ public HotspotNetwork[] newArray(int size) {
+ return new HotspotNetwork[size];
}
};
@Override
public String toString() {
- return new StringBuilder("TetherNetwork[")
+ return new StringBuilder("HotspotNetwork[")
.append("deviceId=").append(mDeviceId)
.append(", networkType=").append(mNetworkType)
- .append(", deviceInfo=").append(mDeviceInfo.toString())
+ .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
.append(", networkName=").append(mNetworkName)
.append(", hotspotSsid=").append(mHotspotSsid)
.append(", hotspotBssid=").append(mHotspotBssid)
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
similarity index 93%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
index 35d5c15..d32d15e 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.sharedconnectivity.app;
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable HotspotNetworkConnectionStatus;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
new file mode 100644
index 0000000..69767f3
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * The status of a connection to a hotspot network after the client called
+ * {@link SharedConnectivityManager#connectHotspotNetwork}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class HotspotNetworkConnectionStatus implements Parcelable {
+
+ /**
+ * Connection status is unknown.
+ */
+ public static final int CONNECTION_STATUS_UNKNOWN = 0;
+
+ /**
+ * The connection is being initiated.
+ */
+ public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1;
+
+ /**
+ * Device providing the hotspot failed to initiate it.
+ */
+ public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2;
+
+ /**
+ * Failed to provision tethering.
+ */
+ public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3;
+
+ /**
+ * Timeout while trying to provision tethering.
+ */
+ public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4;
+
+ /**
+ * Device doesn't support tethering.
+ */
+ public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5;
+
+ /**
+ * Device has no cell data.
+ */
+ public static final int CONNECTION_STATUS_NO_CELL_DATA = 6;
+
+ /**
+ * Device failed to enable hotspot
+ */
+ public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7;
+
+ /**
+ * Timeout while trying to enable hotspot
+ */
+ public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8;
+
+ /**
+ * Failed to connect to hotspot
+ */
+ public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9;
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ CONNECTION_STATUS_UNKNOWN,
+ CONNECTION_STATUS_ENABLING_HOTSPOT,
+ CONNECTION_STATUS_UNKNOWN_ERROR,
+ CONNECTION_STATUS_PROVISIONING_FAILED,
+ CONNECTION_STATUS_TETHERING_TIMEOUT,
+ CONNECTION_STATUS_TETHERING_UNSUPPORTED,
+ CONNECTION_STATUS_NO_CELL_DATA,
+ CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED,
+ CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT,
+ CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED,
+ })
+ public @interface ConnectionStatus {
+ }
+
+ @ConnectionStatus
+ private final int mStatus;
+ private final HotspotNetwork mHotspotNetwork;
+ private final Bundle mExtras;
+
+ /**
+ * Builder class for {@link HotspotNetworkConnectionStatus}.
+ */
+ public static final class Builder {
+ @ConnectionStatus
+ private int mStatus;
+ private HotspotNetwork mHotspotNetwork;
+ private Bundle mExtras;
+
+ /**
+ * Sets the status of the connection
+ *
+ * @return Returns the Builder object.
+ */
+ @NonNull
+ public Builder setStatus(@ConnectionStatus int status) {
+ mStatus = status;
+ return this;
+ }
+
+ /**
+ * Sets the {@link HotspotNetwork} object of the connection.
+ *
+ * @return Returns the Builder object.
+ */
+ @NonNull
+ public Builder setHotspotNetwork(@NonNull HotspotNetwork hotspotNetwork) {
+ mHotspotNetwork = hotspotNetwork;
+ return this;
+ }
+
+ /**
+ * Sets the extras bundle
+ *
+ * @return Returns the Builder object.
+ */
+ @NonNull
+ public Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Builds the {@link HotspotNetworkConnectionStatus} object.
+ *
+ * @return Returns the built {@link HotspotNetworkConnectionStatus} object.
+ */
+ @NonNull
+ public HotspotNetworkConnectionStatus build() {
+ return new HotspotNetworkConnectionStatus(mStatus, mHotspotNetwork, mExtras);
+ }
+ }
+
+ private static void validate(@ConnectionStatus int status) {
+ if (status != CONNECTION_STATUS_UNKNOWN
+ && status != CONNECTION_STATUS_ENABLING_HOTSPOT
+ && status != CONNECTION_STATUS_UNKNOWN_ERROR
+ && status != CONNECTION_STATUS_PROVISIONING_FAILED
+ && status != CONNECTION_STATUS_TETHERING_TIMEOUT
+ && status != CONNECTION_STATUS_TETHERING_UNSUPPORTED
+ && status != CONNECTION_STATUS_NO_CELL_DATA
+ && status != CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED
+ && status != CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT
+ && status != CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED) {
+ throw new IllegalArgumentException("Illegal connection status");
+ }
+ }
+
+ private HotspotNetworkConnectionStatus(@ConnectionStatus int status,
+ HotspotNetwork hotspotNetwork, Bundle extras) {
+ validate(status);
+ mStatus = status;
+ mHotspotNetwork = hotspotNetwork;
+ mExtras = extras;
+ }
+
+ /**
+ * Gets the status of the connection
+ *
+ * @return Returns true for enabled, false otherwise.
+ */
+ @ConnectionStatus
+ public int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Gets the {@link HotspotNetwork} object of the connection.
+ *
+ * @return Returns a HotspotNetwork object.
+ */
+ @NonNull
+ public HotspotNetwork getHotspotNetwork() {
+ return mHotspotNetwork;
+ }
+
+ /**
+ * Gets the extras Bundle.
+ *
+ * @return Returns a Bundle object.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof HotspotNetworkConnectionStatus)) return false;
+ HotspotNetworkConnectionStatus other = (HotspotNetworkConnectionStatus) obj;
+ return mStatus == other.getStatus()
+ && Objects.equals(mHotspotNetwork, other.getHotspotNetwork());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mStatus, mHotspotNetwork);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mStatus);
+ mHotspotNetwork.writeToParcel(dest, flags);
+ dest.writeBundle(mExtras);
+ }
+
+ /**
+ * Creates a {@link HotspotNetworkConnectionStatus} object from a parcel.
+ *
+ * @hide
+ */
+ @NonNull
+ public static HotspotNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
+ return new HotspotNetworkConnectionStatus(in.readInt(),
+ HotspotNetwork.readFromParcel(in), in.readBundle());
+ }
+
+ @NonNull
+ public static final Creator<HotspotNetworkConnectionStatus> CREATOR = new Creator<>() {
+ @Override
+ public HotspotNetworkConnectionStatus createFromParcel(Parcel in) {
+ return readFromParcel(in);
+ }
+
+ @Override
+ public HotspotNetworkConnectionStatus[] newArray(int size) {
+ return new HotspotNetworkConnectionStatus[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return new StringBuilder("HotspotNetworkConnectionStatus[")
+ .append("status=").append(mStatus)
+ .append("hotspot network=").append(mHotspotNetwork.toString())
+ .append("extras=").append(mExtras.toString())
+ .append("]").toString();
+ }
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
index 1fb1c63..64412bc 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
@@ -20,6 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -38,39 +39,51 @@
*/
@SystemApi
public final class KnownNetwork implements Parcelable {
+
+ /**
+ * Network source is unknown.
+ */
+ public static final int NETWORK_SOURCE_UNKNOWN = 0;
+
/**
* Network is known by a nearby device with the same user account.
*/
- public static final int NETWORK_SOURCE_NEARBY_SELF = 0;
+ public static final int NETWORK_SOURCE_NEARBY_SELF = 1;
/**
* Network is known via cloud storage associated with this device's user account.
*/
- public static final int NETWORK_SOURCE_CLOUD_SELF = 1;
+ public static final int NETWORK_SOURCE_CLOUD_SELF = 2;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
+ NETWORK_SOURCE_UNKNOWN,
NETWORK_SOURCE_NEARBY_SELF,
NETWORK_SOURCE_CLOUD_SELF
})
- public @interface NetworkSource {}
+ public @interface NetworkSource {
+ }
- @NetworkSource private final int mNetworkSource;
+ @NetworkSource
+ private final int mNetworkSource;
private final String mSsid;
- @SecurityType private final ArraySet<Integer> mSecurityTypes;
- private final DeviceInfo mDeviceInfo;
+ @SecurityType
+ private final ArraySet<Integer> mSecurityTypes;
+ private final NetworkProviderInfo mNetworkProviderInfo;
/**
* Builder class for {@link KnownNetwork}.
*/
public static final class Builder {
- @NetworkSource private int mNetworkSource = -1;
+ @NetworkSource
+ private int mNetworkSource = -1;
private String mSsid;
- @SecurityType private final ArraySet<Integer> mSecurityTypes = new ArraySet<>();
- private android.net.wifi.sharedconnectivity.app.DeviceInfo mDeviceInfo;
+ @SecurityType
+ private final ArraySet<Integer> mSecurityTypes = new ArraySet<>();
+ private NetworkProviderInfo mNetworkProviderInfo;
/**
* Sets the indicated source of the known network.
@@ -110,13 +123,14 @@
/**
* Sets the device information of the device providing connectivity.
+ * Must be set if network source is {@link KnownNetwork#NETWORK_SOURCE_NEARBY_SELF}.
*
- * @param deviceInfo The device information object.
+ * @param networkProviderInfo The device information object.
* @return Returns the Builder object.
*/
@NonNull
- public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
- mDeviceInfo = deviceInfo;
+ public Builder setNetworkProviderInfo(@Nullable NetworkProviderInfo networkProviderInfo) {
+ mNetworkProviderInfo = networkProviderInfo;
return this;
}
@@ -131,13 +145,16 @@
mNetworkSource,
mSsid,
mSecurityTypes,
- mDeviceInfo);
+ mNetworkProviderInfo);
}
}
- private static void validate(int networkSource, String ssid, Set<Integer> securityTypes) {
- if (networkSource != NETWORK_SOURCE_CLOUD_SELF && networkSource
- != NETWORK_SOURCE_NEARBY_SELF) {
+ private static void validate(@NetworkSource int networkSource, String ssid,
+ @SecurityType Set<Integer> securityTypes,
+ NetworkProviderInfo networkProviderInfo) {
+ if (networkSource != NETWORK_SOURCE_UNKNOWN
+ && networkSource != NETWORK_SOURCE_CLOUD_SELF
+ && networkSource != NETWORK_SOURCE_NEARBY_SELF) {
throw new IllegalArgumentException("Illegal network source");
}
if (TextUtils.isEmpty(ssid)) {
@@ -146,18 +163,22 @@
if (securityTypes.isEmpty()) {
throw new IllegalArgumentException("SecurityTypes must be set");
}
+ if (networkSource == NETWORK_SOURCE_NEARBY_SELF && networkProviderInfo == null) {
+ throw new IllegalArgumentException("Device info must be provided when network source"
+ + " is NETWORK_SOURCE_NEARBY_SELF");
+ }
}
private KnownNetwork(
@NetworkSource int networkSource,
@NonNull String ssid,
@NonNull @SecurityType ArraySet<Integer> securityTypes,
- @NonNull DeviceInfo deviceInfo) {
- validate(networkSource, ssid, securityTypes);
+ @Nullable NetworkProviderInfo networkProviderInfo) {
+ validate(networkSource, ssid, securityTypes, networkProviderInfo);
mNetworkSource = networkSource;
mSsid = ssid;
mSecurityTypes = new ArraySet<>(securityTypes);
- mDeviceInfo = deviceInfo;
+ mNetworkProviderInfo = networkProviderInfo;
}
/**
@@ -194,11 +215,12 @@
/**
* Gets the device information of the device providing connectivity.
*
- * @return Returns the information of the device providing the known network.
+ * @return Returns the information of the device providing the known network. Can be null if the
+ * network source is cloud or unknown.
*/
- @NonNull
- public DeviceInfo getDeviceInfo() {
- return mDeviceInfo;
+ @Nullable
+ public NetworkProviderInfo getNetworkProviderInfo() {
+ return mNetworkProviderInfo;
}
@Override
@@ -208,12 +230,12 @@
return mNetworkSource == other.getNetworkSource()
&& Objects.equals(mSsid, other.getSsid())
&& Objects.equals(mSecurityTypes, other.getSecurityTypes())
- && Objects.equals(mDeviceInfo, other.getDeviceInfo());
+ && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo());
}
@Override
public int hashCode() {
- return Objects.hash(mNetworkSource, mSsid, mSecurityTypes, mDeviceInfo);
+ return Objects.hash(mNetworkSource, mSsid, mSecurityTypes, mNetworkProviderInfo);
}
@Override
@@ -226,7 +248,7 @@
dest.writeInt(mNetworkSource);
dest.writeString(mSsid);
dest.writeArraySet(mSecurityTypes);
- mDeviceInfo.writeToParcel(dest, flags);
+ mNetworkProviderInfo.writeToParcel(dest, flags);
}
/**
@@ -238,7 +260,7 @@
public static KnownNetwork readFromParcel(@NonNull Parcel in) {
return new KnownNetwork(in.readInt(), in.readString(),
(ArraySet<Integer>) in.readArraySet(null),
- DeviceInfo.readFromParcel(in));
+ NetworkProviderInfo.readFromParcel(in));
}
@NonNull
@@ -260,7 +282,7 @@
.append("NetworkSource=").append(mNetworkSource)
.append(", ssid=").append(mSsid)
.append(", securityTypes=").append(mSecurityTypes.toString())
- .append(", deviceInfo=").append(mDeviceInfo.toString())
+ .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
.append("]").toString();
}
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
index b2f04ff..6bd0a5e 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
@@ -120,8 +120,16 @@
}
}
+ private static void validate(@ConnectionStatus int status) {
+ if (status != CONNECTION_STATUS_UNKNOWN && status != CONNECTION_STATUS_SAVED
+ && status != CONNECTION_STATUS_SAVE_FAILED) {
+ throw new IllegalArgumentException("Illegal connection status");
+ }
+ }
+
private KnownNetworkConnectionStatus(@ConnectionStatus int status, KnownNetwork knownNetwork,
Bundle extras) {
+ validate(status);
mStatus = status;
mKnownNetwork = knownNetwork;
mExtras = extras;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
similarity index 95%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
index 35d5c15..f3cbbc2 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.sharedconnectivity.app;
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable NetworkProviderInfo;
\ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
similarity index 79%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index 52abf33..ed4d699 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -36,7 +36,7 @@
* @hide
*/
@SystemApi
-public final class DeviceInfo implements Parcelable {
+public final class NetworkProviderInfo implements Parcelable {
/**
* Device type providing connectivity is unknown.
@@ -59,6 +59,16 @@
public static final int DEVICE_TYPE_LAPTOP = 3;
/**
+ * Device providing connectivity is a watch.
+ */
+ public static final int DEVICE_TYPE_WATCH = 4;
+
+ /**
+ * Device providing connectivity is a watch.
+ */
+ public static final int DEVICE_TYPE_AUTO = 5;
+
+ /**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@@ -66,18 +76,22 @@
DEVICE_TYPE_UNKNOWN,
DEVICE_TYPE_PHONE,
DEVICE_TYPE_TABLET,
- DEVICE_TYPE_LAPTOP
+ DEVICE_TYPE_LAPTOP,
+ DEVICE_TYPE_WATCH,
+ DEVICE_TYPE_AUTO
})
- public @interface DeviceType {}
+ public @interface DeviceType {
+ }
- @DeviceType private final int mDeviceType;
+ @DeviceType
+ private final int mDeviceType;
private final String mDeviceName;
private final String mModelName;
private final int mBatteryPercentage;
private final int mConnectionStrength;
/**
- * Builder class for {@link DeviceInfo}.
+ * Builder class for {@link NetworkProviderInfo}.
*/
public static final class Builder {
private int mDeviceType;
@@ -86,7 +100,12 @@
private int mBatteryPercentage;
private int mConnectionStrength;
- public Builder() {}
+ public Builder(@NonNull String deviceName, @NonNull String modelName) {
+ Objects.requireNonNull(deviceName);
+ Objects.requireNonNull(modelName);
+ mDeviceName = deviceName;
+ mModelName = modelName;
+ }
/**
* Sets the device type that provides connectivity.
@@ -108,6 +127,7 @@
*/
@NonNull
public Builder setDeviceName(@NonNull String deviceName) {
+ Objects.requireNonNull(deviceName);
mDeviceName = deviceName;
return this;
}
@@ -120,6 +140,7 @@
*/
@NonNull
public Builder setModelName(@NonNull String modelName) {
+ Objects.requireNonNull(modelName);
mModelName = modelName;
return this;
}
@@ -149,29 +170,24 @@
}
/**
- * Builds the {@link DeviceInfo} object.
+ * Builds the {@link NetworkProviderInfo} object.
*
- * @return Returns the built {@link DeviceInfo} object.
+ * @return Returns the built {@link NetworkProviderInfo} object.
*/
@NonNull
- public DeviceInfo build() {
- return new DeviceInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
+ public NetworkProviderInfo build() {
+ return new NetworkProviderInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
mConnectionStrength);
}
}
- private static void validate(int deviceType, String deviceName, String modelName,
+ private static void validate(@DeviceType int deviceType, String deviceName, String modelName,
int batteryPercentage, int connectionStrength) {
if (deviceType != DEVICE_TYPE_UNKNOWN && deviceType != DEVICE_TYPE_PHONE
- && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP) {
+ && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP
+ && deviceType != DEVICE_TYPE_WATCH && deviceType != DEVICE_TYPE_AUTO) {
throw new IllegalArgumentException("Illegal device type");
}
- if (Objects.isNull(deviceName)) {
- throw new IllegalArgumentException("DeviceName must be set");
- }
- if (Objects.isNull(modelName)) {
- throw new IllegalArgumentException("ModelName must be set");
- }
if (batteryPercentage < 0 || batteryPercentage > 100) {
throw new IllegalArgumentException("BatteryPercentage must be in range 0-100");
}
@@ -180,7 +196,7 @@
}
}
- private DeviceInfo(@DeviceType int deviceType, @NonNull String deviceName,
+ private NetworkProviderInfo(@DeviceType int deviceType, @NonNull String deviceName,
@NonNull String modelName, int batteryPercentage, int connectionStrength) {
validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
mDeviceType = deviceType;
@@ -242,8 +258,8 @@
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof DeviceInfo)) return false;
- DeviceInfo other = (DeviceInfo) obj;
+ if (!(obj instanceof NetworkProviderInfo)) return false;
+ NetworkProviderInfo other = (NetworkProviderInfo) obj;
return mDeviceType == other.getDeviceType()
&& Objects.equals(mDeviceName, other.mDeviceName)
&& Objects.equals(mModelName, other.mModelName)
@@ -256,6 +272,7 @@
return Objects.hash(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
mConnectionStrength);
}
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mDeviceType);
@@ -271,32 +288,32 @@
}
/**
- * Creates a {@link DeviceInfo} object from a parcel.
+ * Creates a {@link NetworkProviderInfo} object from a parcel.
*
* @hide
*/
@NonNull
- public static DeviceInfo readFromParcel(@NonNull Parcel in) {
- return new DeviceInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
+ public static NetworkProviderInfo readFromParcel(@NonNull Parcel in) {
+ return new NetworkProviderInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
in.readInt());
}
@NonNull
- public static final Creator<DeviceInfo> CREATOR = new Creator<DeviceInfo>() {
+ public static final Creator<NetworkProviderInfo> CREATOR = new Creator<NetworkProviderInfo>() {
@Override
- public DeviceInfo createFromParcel(Parcel in) {
+ public NetworkProviderInfo createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
- public DeviceInfo[] newArray(int size) {
- return new DeviceInfo[size];
+ public NetworkProviderInfo[] newArray(int size) {
+ return new NetworkProviderInfo[size];
}
};
@Override
public String toString() {
- return new StringBuilder("DeviceInfo[")
+ return new StringBuilder("NetworkProviderInfo[")
.append("deviceType=").append(mDeviceType)
.append(", deviceName=").append(mDeviceName)
.append(", modelName=").append(mModelName)
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
index d2b9be7..eb04df6 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
@@ -32,14 +32,16 @@
public interface SharedConnectivityClientCallback {
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
- * list of available Tether Networks.
- * @param networks Updated Tether Network list.
+ * list of available Hotspot Networks.
+ *
+ * @param networks Updated Hotspot Network list.
*/
- void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks);
+ void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks);
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
* list of available Known Networks.
+ *
* @param networks Updated Known Network list.
*/
void onKnownNetworksUpdated(@NonNull List<KnownNetwork> networks);
@@ -47,20 +49,23 @@
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
* state of share connectivity settings.
+ *
* @param state The new state.
*/
void onSharedConnectivitySettingsChanged(@NonNull SharedConnectivitySettingsState state);
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
- * status of the current tether network connection.
+ * status of the current hotspot network connection.
+ *
* @param status The new status.
*/
- void onTetherNetworkConnectionStatusChanged(@NonNull TetherNetworkConnectionStatus status);
+ void onHotspotNetworkConnectionStatusChanged(@NonNull HotspotNetworkConnectionStatus status);
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
* status of the current known network connection.
+ *
* @param status The new status.
*/
void onKnownNetworkConnectionStatusChanged(@NonNull KnownNetworkConnectionStatus status);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
index a19510b..684b385d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -19,6 +19,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -48,7 +49,7 @@
* This class is the library used by consumers of Shared Connectivity data to bind to the service,
* receive callbacks from, and send user actions to the service.
*
- * The methods {@link #connectTetherNetwork}, {@link #disconnectTetherNetwork},
+ * The methods {@link #connectHotspotNetwork}, {@link #disconnectHotspotNetwork},
* {@link #connectKnownNetwork} and {@link #forgetKnownNetwork} are not valid and will return false
* if not called between {@link SharedConnectivityClientCallback#onServiceConnected()}
* and {@link SharedConnectivityClientCallback#onServiceDisconnected()} or if
@@ -73,12 +74,11 @@
mCallback = callback;
}
- @Override
- public void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks) {
+ public void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks) {
if (mCallback != null) {
final long token = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> mCallback.onTetherNetworksUpdated(networks));
+ mExecutor.execute(() -> mCallback.onHotspotNetworksUpdated(networks));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -110,14 +110,13 @@
}
}
- @Override
- public void onTetherNetworkConnectionStatusChanged(
- @NonNull TetherNetworkConnectionStatus status) {
+ public void onHotspotNetworkConnectionStatusChanged(
+ @NonNull HotspotNetworkConnectionStatus status) {
if (mCallback != null) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
- mCallback.onTetherNetworkConnectionStatusChanged(status));
+ mCallback.onHotspotNetworkConnectionStatusChanged(status));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -151,7 +150,7 @@
* Creates a new instance of {@link SharedConnectivityManager}.
*
* Automatically binds to implementation of {@link SharedConnectivityService} specified in
- * device overlay.
+ * the device overlay.
*
* @return An instance of {@link SharedConnectivityManager} or null if the shared connectivity
* service is not found.
@@ -258,17 +257,18 @@
}
/**
- * Registers a callback for receiving updates to the list of Tether Networks, Known Networks,
- * shared connectivity settings state, tether network connection status and known network
+ * Registers a callback for receiving updates to the list of Hotspot Networks, Known Networks,
+ * shared connectivity settings state, hotspot network connection status and known network
* connection status.
* The {@link SharedConnectivityClientCallback#onRegisterCallbackFailed} will be called if the
* registration failed.
*
* @param executor The Executor used to invoke the callback.
* @param callback The callback of type {@link SharedConnectivityClientCallback} that is invoked
- * when the service updates either the list of Tether Networks or Known
- * Networks.
+ * when the service updates its data.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public void registerCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull SharedConnectivityClientCallback callback) {
Objects.requireNonNull(executor, "executor cannot be null");
@@ -297,6 +297,8 @@
*
* @return Returns true if the callback was successfully unregistered, false otherwise.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public boolean unregisterCallback(
@NonNull SharedConnectivityClientCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
@@ -325,26 +327,28 @@
return true;
}
- /**
+ /**
* Send command to the implementation of {@link SharedConnectivityService} requesting connection
- * to the specified Tether Network.
+ * to the specified Hotspot Network.
*
- * @param network {@link TetherNetwork} object representing the network the user has requested
+ * @param network {@link HotspotNetwork} object representing the network the user has requested
* a connection to.
* @return Returns true if the service received the command. Does not guarantee that the
- * connection was successful.
+ * connection was successful.
*/
- public boolean connectTetherNetwork(@NonNull TetherNetwork network) {
- Objects.requireNonNull(network, "Tether network cannot be null");
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public boolean connectHotspotNetwork(@NonNull HotspotNetwork network) {
+ Objects.requireNonNull(network, "Hotspot network cannot be null");
if (mService == null) {
return false;
}
try {
- mService.connectTetherNetwork(network);
+ mService.connectHotspotNetwork(network);
} catch (RemoteException e) {
- Log.e(TAG, "Exception in connectTetherNetwork", e);
+ Log.e(TAG, "Exception in connectHotspotNetwork", e);
return false;
}
return true;
@@ -352,22 +356,24 @@
/**
* Send command to the implementation of {@link SharedConnectivityService} requesting
- * disconnection from the active Tether Network.
+ * disconnection from the active Hotspot Network.
*
- * @param network {@link TetherNetwork} object representing the network the user has requested
+ * @param network {@link HotspotNetwork} object representing the network the user has requested
* to disconnect from.
* @return Returns true if the service received the command. Does not guarantee that the
- * disconnection was successful.
+ * disconnection was successful.
*/
- public boolean disconnectTetherNetwork(@NonNull TetherNetwork network) {
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public boolean disconnectHotspotNetwork(@NonNull HotspotNetwork network) {
if (mService == null) {
return false;
}
try {
- mService.disconnectTetherNetwork(network);
+ mService.disconnectHotspotNetwork(network);
} catch (RemoteException e) {
- Log.e(TAG, "Exception in disconnectTetherNetwork", e);
+ Log.e(TAG, "Exception in disconnectHotspotNetwork", e);
return false;
}
return true;
@@ -380,8 +386,10 @@
* @param network {@link KnownNetwork} object representing the network the user has requested
* a connection to.
* @return Returns true if the service received the command. Does not guarantee that the
- * connection was successful.
+ * connection was successful.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public boolean connectKnownNetwork(@NonNull KnownNetwork network) {
Objects.requireNonNull(network, "Known network cannot be null");
@@ -403,8 +411,10 @@
* the specified Known Network from the list of Known Networks.
*
* @return Returns true if the service received the command. Does not guarantee that the
- * forget action was successful.
+ * forget action was successful.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public boolean forgetKnownNetwork(@NonNull KnownNetwork network) {
Objects.requireNonNull(network, "Known network cannot be null");
@@ -422,20 +432,22 @@
}
/**
- * Gets the list of tether networks the user can select to connect to.
+ * Gets the list of hotspot networks the user can select to connect to.
*
- * @return Returns a {@link List} of {@link TetherNetwork} objects, empty list on failure.
+ * @return Returns a {@link List} of {@link HotspotNetwork} objects, empty list on failure.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@NonNull
- public List<TetherNetwork> getTetherNetworks() {
+ public List<HotspotNetwork> getHotspotNetworks() {
if (mService == null) {
return List.of();
}
try {
- return mService.getTetherNetworks();
+ return mService.getHotspotNetworks();
} catch (RemoteException e) {
- Log.e(TAG, "Exception in getTetherNetworks", e);
+ Log.e(TAG, "Exception in getHotspotNetworks", e);
}
return List.of();
}
@@ -445,6 +457,8 @@
*
* @return Returns a {@link List} of {@link KnownNetwork} objects, empty list on failure.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@NonNull
public List<KnownNetwork> getKnownNetworks() {
if (mService == null) {
@@ -465,6 +479,8 @@
* @return Returns a {@link SharedConnectivitySettingsState} object with the state, null on
* failure.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Nullable
public SharedConnectivitySettingsState getSettingsState() {
if (mService == null) {
@@ -480,22 +496,24 @@
}
/**
- * Gets the connection status of the tether network the user selected to connect to.
+ * Gets the connection status of the hotspot network the user selected to connect to.
*
- * @return Returns a {@link TetherNetworkConnectionStatus} object with the connection status,
+ * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection status,
* null on failure. If no connection is active the status will be
- * {@link TetherNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
+ * {@link HotspotNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Nullable
- public TetherNetworkConnectionStatus getTetherNetworkConnectionStatus() {
+ public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
if (mService == null) {
return null;
}
try {
- return mService.getTetherNetworkConnectionStatus();
+ return mService.getHotspotNetworkConnectionStatus();
} catch (RemoteException e) {
- Log.e(TAG, "Exception in getTetherNetworkConnectionStatus", e);
+ Log.e(TAG, "Exception in getHotspotNetworkConnectionStatus", e);
}
return null;
}
@@ -507,6 +525,8 @@
* null on failure. If no connection is active the status will be
* {@link KnownNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Nullable
public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
if (mService == null) {
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
deleted file mode 100644
index 6cc4cfe..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-parcelable TetherNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl
deleted file mode 100644
index c677a6c..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-parcelable TetherNetworkConnectionStatus;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java
deleted file mode 100644
index 3cf44ed..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * The status of a connection to an instant tether network after the client called
- * {@link SharedConnectivityManager#connectTetherNetwork}.
- *
- * @hide
- */
-@SystemApi
-public final class TetherNetworkConnectionStatus implements Parcelable {
-
- /**
- * Connection status is unknown.
- */
- public static final int CONNECTION_STATUS_UNKNOWN = 0;
-
- /**
- * The connection is being initiated.
- */
- public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1;
-
- /**
- * Device providing the hotspot failed to initiate it.
- */
- public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2;
-
- /**
- * Failed to provision tethering.
- */
- public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3;
-
- /**
- * Timeout while trying to provision tethering.
- */
- public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4;
-
- /**
- * Device doesn't support tethering.
- */
- public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5;
-
- /**
- * Device has no cell data.
- */
- public static final int CONNECTION_STATUS_NO_CELL_DATA = 6;
-
- /**
- * Device failed to enable hotspot
- */
- public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7;
-
- /**
- * Timeout while trying to enable hotspot
- */
- public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8;
-
- /**
- * Failed to connect to hotspot
- */
- public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9;
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- CONNECTION_STATUS_UNKNOWN,
- CONNECTION_STATUS_ENABLING_HOTSPOT,
- CONNECTION_STATUS_UNKNOWN_ERROR,
- CONNECTION_STATUS_PROVISIONING_FAILED,
- CONNECTION_STATUS_TETHERING_TIMEOUT,
- CONNECTION_STATUS_TETHERING_UNSUPPORTED,
- CONNECTION_STATUS_NO_CELL_DATA,
- CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED,
- CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT,
- CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED,
- })
- public @interface ConnectionStatus {}
-
- @ConnectionStatus private final int mStatus;
- private final TetherNetwork mTetherNetwork;
- private final Bundle mExtras;
-
- /**
- * Builder class for {@link TetherNetworkConnectionStatus}.
- */
- public static final class Builder {
- @ConnectionStatus private int mStatus;
- private TetherNetwork mTetherNetwork;
- private Bundle mExtras;
-
- public Builder() {}
-
- /**
- * Sets the status of the connection
- *
- * @return Returns the Builder object.
- */
- @NonNull
- public Builder setStatus(@ConnectionStatus int status) {
- mStatus = status;
- return this;
- }
-
- /**
- * Sets the {@link TetherNetwork} object of the connection.
- *
- * @return Returns the Builder object.
- */
- @NonNull
- public Builder setTetherNetwork(@NonNull TetherNetwork tetherNetwork) {
- mTetherNetwork = tetherNetwork;
- return this;
- }
-
- /**
- * Sets the extras bundle
- *
- * @return Returns the Builder object.
- */
- @NonNull
- public Builder setExtras(@NonNull Bundle extras) {
- mExtras = extras;
- return this;
- }
-
- /**
- * Builds the {@link TetherNetworkConnectionStatus} object.
- *
- * @return Returns the built {@link TetherNetworkConnectionStatus} object.
- */
- @NonNull
- public TetherNetworkConnectionStatus build() {
- return new TetherNetworkConnectionStatus(mStatus, mTetherNetwork, mExtras);
- }
- }
-
- private TetherNetworkConnectionStatus(@ConnectionStatus int status, TetherNetwork tetherNetwork,
- Bundle extras) {
- mStatus = status;
- mTetherNetwork = tetherNetwork;
- mExtras = extras;
- }
-
- /**
- * Gets the status of the connection
- *
- * @return Returns true for enabled, false otherwise.
- */
- @ConnectionStatus
- public int getStatus() {
- return mStatus;
- }
-
- /**
- * Gets the {@link TetherNetwork} object of the connection.
- *
- * @return Returns a TetherNetwork object.
- */
- @NonNull
- public TetherNetwork getTetherNetwork() {
- return mTetherNetwork;
- }
-
- /**
- * Gets the extras Bundle.
- *
- * @return Returns a Bundle object.
- */
- @NonNull
- public Bundle getExtras() {
- return mExtras;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof TetherNetworkConnectionStatus)) return false;
- TetherNetworkConnectionStatus other = (TetherNetworkConnectionStatus) obj;
- return mStatus == other.getStatus()
- && Objects.equals(mTetherNetwork, other.getTetherNetwork());
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mStatus, mTetherNetwork);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mStatus);
- mTetherNetwork.writeToParcel(dest, flags);
- dest.writeBundle(mExtras);
- }
-
- /**
- * Creates a {@link TetherNetworkConnectionStatus} object from a parcel.
- *
- * @hide
- */
- @NonNull
- public static TetherNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
- return new TetherNetworkConnectionStatus(in.readInt(),
- TetherNetwork.readFromParcel(in), in.readBundle());
- }
-
- @NonNull
- public static final Creator<TetherNetworkConnectionStatus> CREATOR = new Creator<>() {
- @Override
- public TetherNetworkConnectionStatus createFromParcel(Parcel in) {
- return readFromParcel(in);
- }
-
- @Override
- public TetherNetworkConnectionStatus[] newArray(int size) {
- return new TetherNetworkConnectionStatus[size];
- }
- };
-
- @Override
- public String toString() {
- return new StringBuilder("TetherNetworkConnectionStatus[")
- .append("status=").append(mStatus)
- .append("tether network=").append(mTetherNetwork.toString())
- .append("extras=").append(mExtras.toString())
- .append("]").toString();
- }
-}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
index 6f6f162..737aa6d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
@@ -19,15 +19,15 @@
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
/*
* @hide
*/
interface ISharedConnectivityCallback {
- oneway void onTetherNetworksUpdated(in List<TetherNetwork> networks);
- oneway void onTetherNetworkConnectionStatusChanged(in TetherNetworkConnectionStatus status);
+ oneway void onHotspotNetworksUpdated(in List<HotspotNetwork> networks);
+ oneway void onHotspotNetworkConnectionStatusChanged(in HotspotNetworkConnectionStatus status);
oneway void onKnownNetworksUpdated(in List<KnownNetwork> networks);
oneway void onKnownNetworkConnectionStatusChanged(in KnownNetworkConnectionStatus status);
oneway void onSharedConnectivitySettingsChanged(in SharedConnectivitySettingsState state);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
index 9f33e99..c81380d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
@@ -17,10 +17,10 @@
package android.net.wifi.sharedconnectivity.service;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
/*
@@ -29,13 +29,13 @@
interface ISharedConnectivityService {
void registerCallback(in ISharedConnectivityCallback callback);
void unregisterCallback(in ISharedConnectivityCallback callback);
- void connectTetherNetwork(in TetherNetwork network);
- void disconnectTetherNetwork(in TetherNetwork network);
+ void connectHotspotNetwork(in HotspotNetwork network);
+ void disconnectHotspotNetwork(in HotspotNetwork network);
void connectKnownNetwork(in KnownNetwork network);
void forgetKnownNetwork(in KnownNetwork network);
- List<TetherNetwork> getTetherNetworks();
+ List<HotspotNetwork> getHotspotNetworks();
List<KnownNetwork> getKnownNetworks();
SharedConnectivitySettingsState getSettingsState();
- TetherNetworkConnectionStatus getTetherNetworkConnectionStatus();
+ HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index d2cea61..c53da9c 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -27,12 +27,12 @@
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -62,14 +62,14 @@
private Handler mHandler;
private final RemoteCallbackList<ISharedConnectivityCallback> mRemoteCallbackList =
new RemoteCallbackList<>();
- private List<TetherNetwork> mTetherNetworks = Collections.emptyList();
+ private List<HotspotNetwork> mHotspotNetworks = Collections.emptyList();
private List<KnownNetwork> mKnownNetworks = Collections.emptyList();
private SharedConnectivitySettingsState mSettingsState =
new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(false)
.setExtras(Bundle.EMPTY).build();
- private TetherNetworkConnectionStatus mTetherNetworkConnectionStatus =
- new TetherNetworkConnectionStatus.Builder()
- .setStatus(TetherNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
+ private HotspotNetworkConnectionStatus mHotspotNetworkConnectionStatus =
+ new HotspotNetworkConnectionStatus.Builder()
+ .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
.setExtras(Bundle.EMPTY).build();
private KnownNetworkConnectionStatus mKnownNetworkConnectionStatus =
new KnownNetworkConnectionStatus.Builder()
@@ -82,66 +82,147 @@
if (DEBUG) Log.i(TAG, "onBind intent=" + intent);
mHandler = new Handler(getMainLooper());
IBinder serviceStub = new ISharedConnectivityService.Stub() {
+
+ /**
+ * Registers a callback for receiving updates to the list of Hotspot Networks, Known
+ * Networks, shared connectivity settings state, hotspot network connection status and
+ * known network connection status.
+ *
+ * @param callback The callback of type {@link ISharedConnectivityCallback} to be called
+ * when there is update to the data.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public void registerCallback(ISharedConnectivityCallback callback) {
checkPermissions();
mHandler.post(() -> onRegisterCallback(callback));
}
+ /**
+ * Unregisters a previously registered callback.
+ *
+ * @param callback The callback to unregister.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public void unregisterCallback(ISharedConnectivityCallback callback) {
checkPermissions();
mHandler.post(() -> onUnregisterCallback(callback));
}
+ /**
+ * Connects to a hotspot network.
+ *
+ * @param network The network to connect to.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
- public void connectTetherNetwork(TetherNetwork network) {
+ public void connectHotspotNetwork(HotspotNetwork network) {
checkPermissions();
- mHandler.post(() -> onConnectTetherNetwork(network));
+ mHandler.post(() -> onConnectHotspotNetwork(network));
}
- @Override
- public void disconnectTetherNetwork(TetherNetwork network) {
+ /**
+ * Disconnects from a previously connected hotspot network.
+ *
+ * @param network The network to disconnect from.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void disconnectHotspotNetwork(HotspotNetwork network) {
checkPermissions();
- mHandler.post(() -> onDisconnectTetherNetwork(network));
+ mHandler.post(() -> onDisconnectHotspotNetwork(network));
}
+ /**
+ * Adds a known network to the available networks on the device and connects to it.
+ *
+ * @param network The network to connect to.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public void connectKnownNetwork(KnownNetwork network) {
checkPermissions();
mHandler.post(() -> onConnectKnownNetwork(network));
}
+ /**
+ * Removes a known network from the available networks on the device which will also
+ * disconnect the device from the network if it is connected to it.
+ *
+ * @param network The network to forget.
+ */
@Override
public void forgetKnownNetwork(KnownNetwork network) {
checkPermissions();
mHandler.post(() -> onForgetKnownNetwork(network));
}
+ /**
+ * Gets the list of hotspot networks the user can select to connect to.
+ *
+ * @return Returns a {@link List} of {@link HotspotNetwork} objects
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
- public List<TetherNetwork> getTetherNetworks() {
+ public List<HotspotNetwork> getHotspotNetworks() {
checkPermissions();
- return mTetherNetworks;
+ return mHotspotNetworks;
}
+ /**
+ * Gets the list of known networks the user can select to connect to.
+ *
+ * @return Returns a {@link List} of {@link KnownNetwork} objects.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public List<KnownNetwork> getKnownNetworks() {
checkPermissions();
return mKnownNetworks;
}
+ /**
+ * Gets the shared connectivity settings state.
+ *
+ * @return Returns a {@link SharedConnectivitySettingsState} object with the state.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public SharedConnectivitySettingsState getSettingsState() {
checkPermissions();
return mSettingsState;
}
+ /**
+ * Gets the connection status of the hotspot network the user selected to connect to.
+ *
+ * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection
+ * status.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
- public TetherNetworkConnectionStatus getTetherNetworkConnectionStatus() {
+ public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
checkPermissions();
- return mTetherNetworkConnectionStatus;
+ return mHotspotNetworkConnectionStatus;
}
+ /**
+ * Gets the connection status of the known network the user selected to connect to.
+ *
+ * @return Returns a {@link KnownNetworkConnectionStatus} object with the connection
+ * status.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
checkPermissions();
@@ -172,7 +253,8 @@
/** @hide */
@TestApi
- public void onBind() {}
+ public void onBind() {
+ }
private void onRegisterCallback(ISharedConnectivityCallback callback) {
mRemoteCallbackList.register(callback);
@@ -183,23 +265,23 @@
}
/**
- * Implementing application should call this method to provide an up-to-date list of Tether
+ * Implementing application should call this method to provide an up-to-date list of Hotspot
* Networks to be displayed to the user.
*
* This method updates the cached list and notifies all registered callbacks. Any callbacks that
* are inaccessible will be unregistered.
*
- * @param networks The updated list of {@link TetherNetwork} objects.
+ * @param networks The updated list of {@link HotspotNetwork} objects.
*/
- public final void setTetherNetworks(@NonNull List<TetherNetwork> networks) {
- mTetherNetworks = networks;
+ public final void setHotspotNetworks(@NonNull List<HotspotNetwork> networks) {
+ mHotspotNetworks = networks;
int count = mRemoteCallbackList.beginBroadcast();
for (int i = 0; i < count; i++) {
try {
- mRemoteCallbackList.getBroadcastItem(i).onTetherNetworksUpdated(mTetherNetworks);
+ mRemoteCallbackList.getBroadcastItem(i).onHotspotNetworksUpdated(mHotspotNetworks);
} catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in setTetherNetworks", e);
+ if (DEBUG) Log.w(TAG, "Exception in setHotspotNetworks", e);
}
}
mRemoteCallbackList.finishBroadcast();
@@ -236,7 +318,7 @@
* that are inaccessible will be unregistered.
*
* @param settingsState The updated state {@link SharedConnectivitySettingsState}
- * objects.
+ * objects.
*/
public final void setSettingsState(@NonNull SharedConnectivitySettingsState settingsState) {
mSettingsState = settingsState;
@@ -255,23 +337,22 @@
/**
* Implementing application should call this method to provide an up-to-date status of enabling
- * and connecting to the tether network.
+ * and connecting to the hotspot network.
*
- * @param status The updated status {@link TetherNetworkConnectionStatus} of the connection.
- *
+ * @param status The updated status {@link HotspotNetworkConnectionStatus} of the connection.
*/
- public final void updateTetherNetworkConnectionStatus(
- @NonNull TetherNetworkConnectionStatus status) {
- mTetherNetworkConnectionStatus = status;
+ public final void updateHotspotNetworkConnectionStatus(
+ @NonNull HotspotNetworkConnectionStatus status) {
+ mHotspotNetworkConnectionStatus = status;
int count = mRemoteCallbackList.beginBroadcast();
for (int i = 0; i < count; i++) {
try {
mRemoteCallbackList
- .getBroadcastItem(i).onTetherNetworkConnectionStatusChanged(
- mTetherNetworkConnectionStatus);
+ .getBroadcastItem(i).onHotspotNetworkConnectionStatusChanged(
+ mHotspotNetworkConnectionStatus);
} catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in updateTetherNetworkConnectionStatus", e);
+ if (DEBUG) Log.w(TAG, "Exception in updateHotspotNetworkConnectionStatus", e);
}
}
mRemoteCallbackList.finishBroadcast();
@@ -282,7 +363,6 @@
* connecting to a known network.
*
* @param status The updated status {@link KnownNetworkConnectionStatus} of the connection.
- *
*/
public final void updateKnownNetworkConnectionStatus(
@NonNull KnownNetworkConnectionStatus status) {
@@ -304,20 +384,20 @@
/**
* Implementing application should implement this method.
*
- * Implementation should initiate a connection to the Tether Network indicated.
+ * Implementation should initiate a connection to the Hotspot Network indicated.
*
- * @param network Object identifying the Tether Network the user has requested a connection to.
+ * @param network Object identifying the Hotspot Network the user has requested a connection to.
*/
- public abstract void onConnectTetherNetwork(@NonNull TetherNetwork network);
+ public abstract void onConnectHotspotNetwork(@NonNull HotspotNetwork network);
/**
* Implementing application should implement this method.
*
- * Implementation should initiate a disconnection from the active Tether Network.
+ * Implementation should initiate a disconnection from the active Hotspot Network.
*
- * @param network Object identifying the Tether Network the user has requested to disconnect.
+ * @param network Object identifying the Hotspot Network the user has requested to disconnect.
*/
- public abstract void onDisconnectTetherNetwork(@NonNull TetherNetwork network);
+ public abstract void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network);
/**
* Implementing application should implement this method.
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
similarity index 62%
rename from wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
rename to wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
index 0844364..b18ab50 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
@@ -18,10 +18,10 @@
import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
import static com.google.common.truth.Truth.assertThat;
@@ -35,14 +35,15 @@
import java.util.Arrays;
/**
- * Unit tests for {@link TetherNetworkConnectionStatus}.
+ * Unit tests for {@link HotspotNetworkConnectionStatus}.
*/
@SmallTest
-public class TetherNetworkConnectionStatusTest {
+public class HotspotNetworkConnectionStatusTest {
private static final long DEVICE_ID = 11L;
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
private static final String NETWORK_NAME = "TEST_NETWORK";
private static final String HOTSPOT_SSID = "TEST_SSID";
@@ -57,7 +58,7 @@
*/
@Test
public void testParcelOperation() {
- TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
Parcel parcelW = Parcel.obtain();
status.writeToParcel(parcelW, 0);
@@ -67,8 +68,8 @@
Parcel parcelR = Parcel.obtain();
parcelR.unmarshall(bytes, 0, bytes.length);
parcelR.setDataPosition(0);
- TetherNetworkConnectionStatus fromParcel =
- TetherNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
+ HotspotNetworkConnectionStatus fromParcel =
+ HotspotNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
assertThat(fromParcel).isEqualTo(status);
assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
@@ -79,16 +80,16 @@
*/
@Test
public void testEqualsOperation() {
- TetherNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
- TetherNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
assertThat(status1).isEqualTo(status2);
- TetherNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
+ HotspotNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
.setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
assertThat(builder.build()).isNotEqualTo(status1);
builder = buildConnectionStatusBuilder()
- .setTetherNetwork(buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
+ .setHotspotNetwork(buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
assertThat(builder.build()).isNotEqualTo(status1);
}
@@ -97,24 +98,24 @@
*/
@Test
public void testGetMethods() {
- TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_ENABLING_HOTSPOT);
- assertThat(status.getTetherNetwork()).isEqualTo(buildTetherNetworkBuilder().build());
+ assertThat(status.getHotspotNetwork()).isEqualTo(buildHotspotNetworkBuilder().build());
assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
}
@Test
public void testHashCode() {
- TetherNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
- TetherNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
}
- private TetherNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
- return new TetherNetworkConnectionStatus.Builder()
+ private HotspotNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
+ return new HotspotNetworkConnectionStatus.Builder()
.setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
- .setTetherNetwork(buildTetherNetworkBuilder().build())
+ .setHotspotNetwork(buildHotspotNetworkBuilder().build())
.setExtras(buildBundle());
}
@@ -124,11 +125,11 @@
return bundle;
}
- private TetherNetwork.Builder buildTetherNetworkBuilder() {
- TetherNetwork.Builder builder = new TetherNetwork.Builder()
+ private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
+ HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
.setDeviceId(DEVICE_ID)
- .setDeviceInfo(DEVICE_INFO)
- .setNetworkType(NETWORK_TYPE)
+ .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE)
.setNetworkName(NETWORK_NAME)
.setHotspotSsid(HOTSPOT_SSID)
.setHotspotBssid(HOTSPOT_BSSID);
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
similarity index 62%
rename from wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
rename to wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
index a50d767..8e396b6 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
@@ -19,10 +19,10 @@
import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_WIFI;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_WIFI;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
import static com.google.common.truth.Truth.assertThat;
@@ -36,14 +36,15 @@
import java.util.Arrays;
/**
- * Unit tests for {@link TetherNetwork}.
+ * Unit tests for {@link HotspotNetwork}.
*/
@SmallTest
-public class TetherNetworkTest {
+public class HotspotNetworkTest {
private static final long DEVICE_ID = 11L;
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
private static final String NETWORK_NAME = "TEST_NETWORK";
private static final String HOTSPOT_SSID = "TEST_SSID";
@@ -51,9 +52,10 @@
private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
private static final long DEVICE_ID_1 = 111L;
- private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final int NETWORK_TYPE_1 = NETWORK_TYPE_WIFI;
private static final String NETWORK_NAME_1 = "TEST_NETWORK1";
private static final String HOTSPOT_SSID_1 = "TEST_SSID1";
@@ -65,7 +67,7 @@
*/
@Test
public void testParcelOperation() {
- TetherNetwork network = buildTetherNetworkBuilder().build();
+ HotspotNetwork network = buildHotspotNetworkBuilder().build();
Parcel parcelW = Parcel.obtain();
network.writeToParcel(parcelW, 0);
@@ -75,7 +77,7 @@
Parcel parcelR = Parcel.obtain();
parcelR.unmarshall(bytes, 0, bytes.length);
parcelR.setDataPosition(0);
- TetherNetwork fromParcel = TetherNetwork.CREATOR.createFromParcel(parcelR);
+ HotspotNetwork fromParcel = HotspotNetwork.CREATOR.createFromParcel(parcelR);
assertThat(fromParcel).isEqualTo(network);
assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
@@ -86,30 +88,30 @@
*/
@Test
public void testEqualsOperation() {
- TetherNetwork network1 = buildTetherNetworkBuilder().build();
- TetherNetwork network2 = buildTetherNetworkBuilder().build();
+ HotspotNetwork network1 = buildHotspotNetworkBuilder().build();
+ HotspotNetwork network2 = buildHotspotNetworkBuilder().build();
assertThat(network1).isEqualTo(network2);
- TetherNetwork.Builder builder = buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1);
+ HotspotNetwork.Builder builder = buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1);
assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildTetherNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
+ builder = buildHotspotNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildTetherNetworkBuilder().setNetworkType(NETWORK_TYPE_1);
+ builder = buildHotspotNetworkBuilder().setHostNetworkType(NETWORK_TYPE_1);
assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildTetherNetworkBuilder().setNetworkName(NETWORK_NAME_1);
+ builder = buildHotspotNetworkBuilder().setNetworkName(NETWORK_NAME_1);
assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildTetherNetworkBuilder().setHotspotSsid(HOTSPOT_SSID_1);
+ builder = buildHotspotNetworkBuilder().setHotspotSsid(HOTSPOT_SSID_1);
assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildTetherNetworkBuilder().setHotspotBssid(HOTSPOT_BSSID_1);
+ builder = buildHotspotNetworkBuilder().setHotspotBssid(HOTSPOT_BSSID_1);
assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildTetherNetworkBuilder();
- TetherNetwork.Builder builder1 = buildTetherNetworkBuilder();
+ builder = buildHotspotNetworkBuilder();
+ HotspotNetwork.Builder builder1 = buildHotspotNetworkBuilder();
Arrays.stream(HOTSPOT_SECURITY_TYPES_1).forEach(builder1::addHotspotSecurityType);
assertThat(builder1.build()).isNotEqualTo(builder.build());
@@ -120,13 +122,13 @@
*/
@Test
public void testGetMethods() {
- TetherNetwork network = buildTetherNetworkBuilder().build();
+ HotspotNetwork network = buildHotspotNetworkBuilder().build();
ArraySet<Integer> securityTypes = new ArraySet<>();
Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(securityTypes::add);
assertThat(network.getDeviceId()).isEqualTo(DEVICE_ID);
- assertThat(network.getDeviceInfo()).isEqualTo(DEVICE_INFO);
- assertThat(network.getNetworkType()).isEqualTo(NETWORK_TYPE);
+ assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+ assertThat(network.getHostNetworkType()).isEqualTo(NETWORK_TYPE);
assertThat(network.getNetworkName()).isEqualTo(NETWORK_NAME);
assertThat(network.getHotspotSsid()).isEqualTo(HOTSPOT_SSID);
assertThat(network.getHotspotBssid()).isEqualTo(HOTSPOT_BSSID);
@@ -135,17 +137,17 @@
@Test
public void testHashCode() {
- TetherNetwork network1 = buildTetherNetworkBuilder().build();
- TetherNetwork network2 = buildTetherNetworkBuilder().build();
+ HotspotNetwork network1 = buildHotspotNetworkBuilder().build();
+ HotspotNetwork network2 = buildHotspotNetworkBuilder().build();
assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
}
- private TetherNetwork.Builder buildTetherNetworkBuilder() {
- TetherNetwork.Builder builder = new TetherNetwork.Builder()
+ private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
+ HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
.setDeviceId(DEVICE_ID)
- .setDeviceInfo(DEVICE_INFO)
- .setNetworkType(NETWORK_TYPE)
+ .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE)
.setNetworkName(NETWORK_NAME)
.setHotspotSsid(HOTSPOT_SSID)
.setHotspotBssid(HOTSPOT_BSSID);
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
index 8a0f21e..f98a0fc 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
@@ -17,10 +17,10 @@
package android.net.wifi.sharedconnectivity.app;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
import static com.google.common.truth.Truth.assertThat;
@@ -41,9 +41,10 @@
private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
private static final String SSID = "TEST_SSID";
private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final String SSID_1 = "TEST_SSID1";
private static final String BUNDLE_KEY = "INT-KEY";
private static final int BUNDLE_VALUE = 1;
@@ -121,8 +122,8 @@
}
private KnownNetwork.Builder buildKnownNetworkBuilder() {
- KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
- .setSsid(SSID).setDeviceInfo(DEVICE_INFO);
+ KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+ .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
return builder;
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
index 872dd2e..1ecba76 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
@@ -18,10 +18,10 @@
import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_CLOUD_SELF;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
import static com.google.common.truth.Truth.assertThat;
@@ -43,15 +43,17 @@
private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
private static final String SSID = "TEST_SSID";
private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final int NETWORK_SOURCE_1 = NETWORK_SOURCE_CLOUD_SELF;
private static final String SSID_1 = "TEST_SSID1";
private static final int[] SECURITY_TYPES_1 = {SECURITY_TYPE_PSK};
- private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME_1")
- .setModelName("TEST_MODEL_1").setConnectionStrength(3).setBatteryPercentage(33).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+ new NetworkProviderInfo.Builder("TEST_NAME_1", "TEST_MODEL_1")
+ .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(3)
+ .setBatteryPercentage(33).build();
/**
* Verifies parcel serialization/deserialization.
@@ -94,7 +96,7 @@
Arrays.stream(SECURITY_TYPES_1).forEach(builder::addSecurityType);
assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildKnownNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
+ builder = buildKnownNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
assertThat(builder.build()).isNotEqualTo(network1);
}
@@ -110,7 +112,7 @@
assertThat(network.getNetworkSource()).isEqualTo(NETWORK_SOURCE);
assertThat(network.getSsid()).isEqualTo(SSID);
assertThat(network.getSecurityTypes()).containsExactlyElementsIn(securityTypes);
- assertThat(network.getDeviceInfo()).isEqualTo(DEVICE_INFO);
+ assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
}
@Test
@@ -122,8 +124,8 @@
}
private KnownNetwork.Builder buildKnownNetworkBuilder() {
- KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
- .setSsid(SSID).setDeviceInfo(DEVICE_INFO);
+ KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+ .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
return builder;
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
similarity index 68%
rename from wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
rename to wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
index e6595eb..8f35d8d 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
@@ -16,8 +16,8 @@
package android.net.wifi.sharedconnectivity.app;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_LAPTOP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_LAPTOP;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
import static com.google.common.truth.Truth.assertThat;
@@ -28,10 +28,10 @@
import org.junit.Test;
/**
- * Unit tests for {@link DeviceInfo}.
+ * Unit tests for {@link NetworkProviderInfo}.
*/
@SmallTest
-public class DeviceInfoTest {
+public class NetworkProviderInfoTest {
private static final int DEVICE_TYPE = DEVICE_TYPE_PHONE;
private static final String DEVICE_NAME = "TEST_NAME";
@@ -50,7 +50,7 @@
*/
@Test
public void testParcelOperation() {
- DeviceInfo info = buildDeviceInfoBuilder().build();
+ NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
Parcel parcelW = Parcel.obtain();
info.writeToParcel(parcelW, 0);
@@ -60,7 +60,7 @@
Parcel parcelR = Parcel.obtain();
parcelR.unmarshall(bytes, 0, bytes.length);
parcelR.setDataPosition(0);
- DeviceInfo fromParcel = DeviceInfo.CREATOR.createFromParcel(parcelR);
+ NetworkProviderInfo fromParcel = NetworkProviderInfo.CREATOR.createFromParcel(parcelR);
assertThat(fromParcel).isEqualTo(info);
assertThat(fromParcel.hashCode()).isEqualTo(info.hashCode());
@@ -71,24 +71,25 @@
*/
@Test
public void testEqualsOperation() {
- DeviceInfo info1 = buildDeviceInfoBuilder().build();
- DeviceInfo info2 = buildDeviceInfoBuilder().build();
+ NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+ NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
assertThat(info1).isEqualTo(info2);
- DeviceInfo.Builder builder = buildDeviceInfoBuilder().setDeviceType(DEVICE_TYPE_1);
+ NetworkProviderInfo.Builder builder = buildNetworkProviderInfoBuilder().setDeviceType(
+ DEVICE_TYPE_1);
assertThat(builder.build()).isNotEqualTo(info1);
- builder = buildDeviceInfoBuilder().setDeviceName(DEVICE_NAME_1);
+ builder = buildNetworkProviderInfoBuilder().setDeviceName(DEVICE_NAME_1);
assertThat(builder.build()).isNotEqualTo(info1);
- builder = buildDeviceInfoBuilder().setModelName(DEVICE_MODEL_1);
+ builder = buildNetworkProviderInfoBuilder().setModelName(DEVICE_MODEL_1);
assertThat(builder.build()).isNotEqualTo(info1);
- builder = buildDeviceInfoBuilder()
+ builder = buildNetworkProviderInfoBuilder()
.setBatteryPercentage(BATTERY_PERCENTAGE_1);
assertThat(builder.build()).isNotEqualTo(info1);
- builder = buildDeviceInfoBuilder()
+ builder = buildNetworkProviderInfoBuilder()
.setConnectionStrength(CONNECTION_STRENGTH_1);
assertThat(builder.build()).isNotEqualTo(info1);
}
@@ -98,7 +99,7 @@
*/
@Test
public void testGetMethods() {
- DeviceInfo info = buildDeviceInfoBuilder().build();
+ NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
assertThat(info.getDeviceType()).isEqualTo(DEVICE_TYPE);
assertThat(info.getDeviceName()).isEqualTo(DEVICE_NAME);
assertThat(info.getModelName()).isEqualTo(DEVICE_MODEL);
@@ -108,15 +109,15 @@
@Test
public void testHashCode() {
- DeviceInfo info1 = buildDeviceInfoBuilder().build();
- DeviceInfo info2 = buildDeviceInfoBuilder().build();
+ NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+ NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
assertThat(info1.hashCode()).isEqualTo(info2.hashCode());
}
- private DeviceInfo.Builder buildDeviceInfoBuilder() {
- return new DeviceInfo.Builder().setDeviceType(DEVICE_TYPE).setDeviceName(DEVICE_NAME)
- .setModelName(DEVICE_MODEL).setBatteryPercentage(BATTERY_PERCENTAGE)
+ private NetworkProviderInfo.Builder buildNetworkProviderInfoBuilder() {
+ return new NetworkProviderInfo.Builder(DEVICE_NAME, DEVICE_MODEL).setDeviceType(DEVICE_TYPE)
+ .setBatteryPercentage(BATTERY_PERCENTAGE)
.setConnectionStrength(CONNECTION_STRENGTH);
}
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
index 7c0a8b6..8c573e3 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
@@ -18,9 +18,9 @@
import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
import static com.google.common.truth.Truth.assertThat;
@@ -56,9 +56,10 @@
@SmallTest
public class SharedConnectivityManagerTest {
private static final long DEVICE_ID = 11L;
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
private static final String NETWORK_NAME = "TEST_NETWORK";
private static final String HOTSPOT_SSID = "TEST_SSID";
@@ -72,13 +73,16 @@
private static final String SERVICE_INTENT_ACTION = "TEST_INTENT_ACTION";
- @Mock Context mContext;
+ @Mock
+ Context mContext;
@Mock
ISharedConnectivityService mService;
- @Mock Executor mExecutor;
+ @Mock
+ Executor mExecutor;
@Mock
SharedConnectivityClientCallback mClientCallback;
- @Mock Resources mResources;
+ @Mock
+ Resources mResources;
@Mock
ISharedConnectivityService.Stub mIBinder;
@@ -284,69 +288,69 @@
}
/**
- * Verifies connectTetherNetwork behavior.
+ * Verifies connectHotspotNetwork behavior.
*/
@Test
- public void connectTetherNetwork_serviceNotConnected_shouldFail() {
- TetherNetwork network = buildTetherNetwork();
+ public void connectHotspotNetwork_serviceNotConnected_shouldFail() {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertThat(manager.connectTetherNetwork(network)).isFalse();
+ assertThat(manager.connectHotspotNetwork(network)).isFalse();
}
@Test
- public void connectTetherNetwork() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void connectHotspotNetwork() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- manager.connectTetherNetwork(network);
+ manager.connectHotspotNetwork(network);
- verify(mService).connectTetherNetwork(network);
+ verify(mService).connectHotspotNetwork(network);
}
@Test
- public void connectTetherNetwork_remoteException_shouldFail() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void connectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- doThrow(new RemoteException()).when(mService).connectTetherNetwork(network);
+ doThrow(new RemoteException()).when(mService).connectHotspotNetwork(network);
- assertThat(manager.connectTetherNetwork(network)).isFalse();
+ assertThat(manager.connectHotspotNetwork(network)).isFalse();
}
/**
- * Verifies disconnectTetherNetwork behavior.
+ * Verifies disconnectHotspotNetwork behavior.
*/
@Test
- public void disconnectTetherNetwork_serviceNotConnected_shouldFail() {
- TetherNetwork network = buildTetherNetwork();
+ public void disconnectHotspotNetwork_serviceNotConnected_shouldFail() {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertThat(manager.disconnectTetherNetwork(network)).isFalse();
+ assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
}
@Test
- public void disconnectTetherNetwork() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void disconnectHotspotNetwork() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- manager.disconnectTetherNetwork(network);
+ manager.disconnectHotspotNetwork(network);
- verify(mService).disconnectTetherNetwork(network);
+ verify(mService).disconnectHotspotNetwork(network);
}
@Test
- public void disconnectTetherNetwork_remoteException_shouldFail() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void disconnectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- doThrow(new RemoteException()).when(mService).disconnectTetherNetwork(any());
+ doThrow(new RemoteException()).when(mService).disconnectHotspotNetwork(any());
- assertThat(manager.disconnectTetherNetwork(network)).isFalse();
+ assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
}
/**
@@ -419,7 +423,7 @@
* Verify getters.
*/
@Test
- public void getTetherNetworks_serviceNotConnected_shouldReturnEmptyList() {
+ public void getHotspotNetworks_serviceNotConnected_shouldReturnEmptyList() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
@@ -427,22 +431,22 @@
}
@Test
- public void getTetherNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
+ public void getHotspotNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- doThrow(new RemoteException()).when(mService).getTetherNetworks();
+ doThrow(new RemoteException()).when(mService).getHotspotNetworks();
assertThat(manager.getKnownNetworks()).isEmpty();
}
@Test
- public void getTetherNetworks_shouldReturnNetworksList() throws RemoteException {
+ public void getHotspotNetworks_shouldReturnNetworksList() throws RemoteException {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- List<TetherNetwork> networks = List.of(buildTetherNetwork());
+ List<HotspotNetwork> networks = List.of(buildHotspotNetwork());
manager.setService(mService);
- when(mService.getTetherNetworks()).thenReturn(networks);
+ when(mService.getHotspotNetworks()).thenReturn(networks);
- assertThat(manager.getTetherNetworks()).containsExactly(buildTetherNetwork());
+ assertThat(manager.getHotspotNetworks()).containsExactly(buildHotspotNetwork());
}
@Test
@@ -502,35 +506,35 @@
}
@Test
- public void getTetherNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
+ public void getHotspotNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
throws RemoteException {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertThat(manager.getTetherNetworkConnectionStatus()).isNull();
+ assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
}
@Test
- public void getTetherNetworkConnectionStatus_remoteException_shouldReturnNull()
+ public void getHotspotNetworkConnectionStatus_remoteException_shouldReturnNull()
throws RemoteException {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- doThrow(new RemoteException()).when(mService).getTetherNetworkConnectionStatus();
+ doThrow(new RemoteException()).when(mService).getHotspotNetworkConnectionStatus();
- assertThat(manager.getTetherNetworkConnectionStatus()).isNull();
+ assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
}
@Test
- public void getTetherNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
+ public void getHotspotNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
throws RemoteException {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- TetherNetworkConnectionStatus status = new TetherNetworkConnectionStatus.Builder()
- .setStatus(TetherNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT)
+ HotspotNetworkConnectionStatus status = new HotspotNetworkConnectionStatus.Builder()
+ .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT)
.setExtras(new Bundle()).build();
manager.setService(mService);
- when(mService.getTetherNetworkConnectionStatus()).thenReturn(status);
+ when(mService.getHotspotNetworkConnectionStatus()).thenReturn(status);
- assertThat(manager.getTetherNetworkConnectionStatus()).isEqualTo(status);
+ assertThat(manager.getHotspotNetworkConnectionStatus()).isEqualTo(status);
}
@Test
@@ -571,11 +575,11 @@
.thenReturn(SERVICE_PACKAGE_NAME, SERVICE_INTENT_ACTION);
}
- private TetherNetwork buildTetherNetwork() {
- TetherNetwork.Builder builder = new TetherNetwork.Builder()
+ private HotspotNetwork buildHotspotNetwork() {
+ HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
.setDeviceId(DEVICE_ID)
- .setDeviceInfo(DEVICE_INFO)
- .setNetworkType(NETWORK_TYPE)
+ .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE)
.setNetworkName(NETWORK_NAME)
.setHotspotSsid(HOTSPOT_SSID);
Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
@@ -583,8 +587,8 @@
}
private KnownNetwork buildKnownNetwork() {
- KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
- .setSsid(SSID).setDeviceInfo(DEVICE_INFO);
+ KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+ .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
return builder.build();
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
index 81efa79..19effe5 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -18,11 +18,11 @@
import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
import static com.google.common.truth.Truth.assertThat;
@@ -30,12 +30,12 @@
import android.content.Context;
import android.content.Intent;
-import android.net.wifi.sharedconnectivity.app.DeviceInfo;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
import android.os.Bundle;
import android.os.Looper;
import android.os.RemoteException;
@@ -55,27 +55,30 @@
*/
@SmallTest
public class SharedConnectivityServiceTest {
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
- private static final TetherNetwork TETHER_NETWORK =
- new TetherNetwork.Builder().setDeviceId(1).setDeviceInfo(DEVICE_INFO)
- .setNetworkType(NETWORK_TYPE_CELLULAR).setNetworkName("TEST_NETWORK")
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
+ private static final HotspotNetwork HOTSPOT_NETWORK =
+ new HotspotNetwork.Builder().setDeviceId(1).setNetworkProviderInfo(
+ NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE_CELLULAR).setNetworkName("TEST_NETWORK")
.setHotspotSsid("TEST_SSID").setHotspotBssid("TEST_BSSID")
.addHotspotSecurityType(SECURITY_TYPE_WEP)
.addHotspotSecurityType(SECURITY_TYPE_EAP).build();
- private static final List<TetherNetwork> TETHER_NETWORKS = List.of(TETHER_NETWORK);
+ private static final List<HotspotNetwork> HOTSPOT_NETWORKS = List.of(HOTSPOT_NETWORK);
private static final KnownNetwork KNOWN_NETWORK =
new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE_NEARBY_SELF)
.setSsid("TEST_SSID").addSecurityType(SECURITY_TYPE_WEP)
- .addSecurityType(SECURITY_TYPE_EAP).setDeviceInfo(DEVICE_INFO).build();
+ .addSecurityType(SECURITY_TYPE_EAP).setNetworkProviderInfo(
+ NETWORK_PROVIDER_INFO).build();
private static final List<KnownNetwork> KNOWN_NETWORKS = List.of(KNOWN_NETWORK);
private static final SharedConnectivitySettingsState SETTINGS_STATE =
new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(true)
.setExtras(Bundle.EMPTY).build();
- private static final TetherNetworkConnectionStatus TETHER_NETWORK_CONNECTION_STATUS =
- new TetherNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_UNKNOWN)
- .setTetherNetwork(TETHER_NETWORK).setExtras(Bundle.EMPTY).build();
+ private static final HotspotNetworkConnectionStatus TETHER_NETWORK_CONNECTION_STATUS =
+ new HotspotNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_UNKNOWN)
+ .setHotspotNetwork(HOTSPOT_NETWORK).setExtras(Bundle.EMPTY).build();
private static final KnownNetworkConnectionStatus KNOWN_NETWORK_CONNECTION_STATUS =
new KnownNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_SAVED)
.setKnownNetwork(KNOWN_NETWORK).setExtras(Bundle.EMPTY).build();
@@ -89,16 +92,20 @@
}
@Override
- public void onConnectTetherNetwork(@NonNull TetherNetwork network) {}
+ public void onConnectHotspotNetwork(@NonNull HotspotNetwork network) {
+ }
@Override
- public void onDisconnectTetherNetwork(@NonNull TetherNetwork network) {}
+ public void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network) {
+ }
@Override
- public void onConnectKnownNetwork(@NonNull KnownNetwork network) {}
+ public void onConnectKnownNetwork(@NonNull KnownNetwork network) {
+ }
@Override
- public void onForgetKnownNetwork(@NonNull KnownNetwork network) {}
+ public void onForgetKnownNetwork(@NonNull KnownNetwork network) {
+ }
}
@Before
@@ -115,15 +122,15 @@
}
@Test
- public void getTetherNetworks() throws RemoteException {
+ public void getHotspotNetworks() throws RemoteException {
SharedConnectivityService service = createService();
ISharedConnectivityService.Stub binder =
(ISharedConnectivityService.Stub) service.onBind(new Intent());
- service.setTetherNetworks(TETHER_NETWORKS);
+ service.setHotspotNetworks(HOTSPOT_NETWORKS);
- assertThat(binder.getTetherNetworks())
- .containsExactlyElementsIn(List.copyOf(TETHER_NETWORKS));
+ assertThat(binder.getHotspotNetworks())
+ .containsExactlyElementsIn(List.copyOf(HOTSPOT_NETWORKS));
}
@Test
@@ -150,14 +157,14 @@
}
@Test
- public void updateTetherNetworkConnectionStatus() throws RemoteException {
+ public void updateHotspotNetworkConnectionStatus() throws RemoteException {
SharedConnectivityService service = createService();
ISharedConnectivityService.Stub binder =
(ISharedConnectivityService.Stub) service.onBind(new Intent());
- service.updateTetherNetworkConnectionStatus(TETHER_NETWORK_CONNECTION_STATUS);
+ service.updateHotspotNetworkConnectionStatus(TETHER_NETWORK_CONNECTION_STATUS);
- assertThat(binder.getTetherNetworkConnectionStatus())
+ assertThat(binder.getHotspotNetworkConnectionStatus())
.isEqualTo(TETHER_NETWORK_CONNECTION_STATUS);
}